2013-02-19 40 views
18

Làm cách nào để truy vấn bên dưới được sửa đổi để bao gồm cột cho số hàng (ví dụ: chỉ mục kết quả một lần)?LINQ: Thêm cột RowNumber

var myResult = from currRow in someTable 
       where currRow.someCategory == someCategoryValue 
       orderby currRow.createdDate descending 
       select currRow; 

EDIT1: Tôi đang tìm kết quả là {idx, col1, col2...col-n} không {idx, row}.

EDIT2: Số hàng phải tương ứng với các hàng kết quả chứ không phải các hàng của bảng.

EDIT3: I DataBind các kết quả này vào GridView. Mục tiêu của tôi là thêm cột số hàng vào số GridView. Có lẽ một cách tiếp cận khác sẽ tốt hơn.

+1

bản sao có thể có của [Làm thế nào để bạn thêm trường chỉ mục vào kết quả LINQ] (http://stackoverflow.com/questions/269058/how-do-you-add-an-index-field-to-linq-results) – sloth

+0

Bạn có muốn chỉ mục của hàng trong bảng hoặc chỉ mục của kết quả được lọc không? –

+0

có thể trùng lặp của [thêm chỉ mục vào kết quả truy vấn LINQ] (http://stackoverflow.com/questions/4999365/adding-index-to-linq-query-result) – sloth

Trả lời

25

Sử dụng phương pháp-cú pháp nơi Enumerable.Select có tình trạng quá tải với các chỉ số:

var myResult = someTable.Select((r, i) => new { Row = r, Index = i }) 
    .Where(x => x.Row.someCategory == someCategoryValue) 
    .OrderByDescending(x => x.Row.createdDate); 

Lưu ý rằng phương pháp này giả định rằng bạn muốn index gốc của hàng trong bảng và không có trong lọc do tôi chọn chỉ mục trước khi tôi lọc với Where.

EDIT: Tôi đang tìm kết quả là {idx, col1, col2 ... col-n} không phải là {idx, row}. Số hàng phải tương ứng với các hàng kết quả không phải là các hàng trong bảng.

Sau đó chọn loại vô danh với tất cả các cột bạn cần:

var myResult = someTable.Where(r => r.someCategory == someCategoryValue) 
     .OrderByDescending(r => r.createdDate) 
     .Select((r, i) => new { idx = i, col1 = r.col1, col2 = r.col2, ...col-n = r.ColN }); 
+0

Tôi đang tìm một giải pháp mà unbundles currRow. (xem bài chỉnh sửa chính) – Steven

+0

@Steven: Đã chỉnh sửa câu trả lời của tôi. Bạn có thể sử dụng một loại ẩn danh. –

+0

@Steven: Bạn có thể databind kết quả này thành GridView. Bạn có vấn đề gì? –

4

Sử dụng Select phương pháp này:

dự án mỗi phần tử của một chuỗi thành một hình thức mới bằng cách kết hợp chỉ số của phần tử.

Ví dụ:

var myResult = someTable.Where(currRow => currRow.someCategory == someCategoryValue) 
         .OrderByDescending(currRow => currRow.createdDate) 
         .Select((currRow, index) => new {Row = currRow, Index = index + 1}); 

Để đối phó với chỉnh sửa của bạn:

Nếu bạn muốn có một DataTable như kết quả, bạn có thể đi theo con đường phi LINQ bằng cách đơn giản bằng cách sử dụng DataView và thêm một cột bổ sung sau đó.

someTable.DefaultView.RowFilter = String.Format("someCategory = '{0}'", someCategoryValue); 
someTable.DefaultView.Sort = "createdDate"; 
var resultTable = someTable.DefaultView.ToTable(); 
resultTable.Columns.Add("Number", typeof(int)); 
int i = 0; 
foreach (DataRow row in resultTable.Rows) 
    row["Number"] = ++i; 
+0

Giả sử OP muốn chỉ mục của các hàng sau bộ lọc đã được áp dụng và không phải là chỉ mục của hàng trong bảng. –

1

gì về?

int i; 
var myResult = from currRow in someTable 
      where currRow.someCategory == someCategoryValue 
      orderby currRow.createdDate descending 
      select new {Record = i++, currRow}; 
+1

bạn có thử không? –

3

Chỉ cần cho vui, đây là một thay thế cho Select với hai đối số:

var resultsWithIndexes = myResult.Zip(Enumerable.Range(1, int.MaxValue - 1), 
             (o, i) => new { Index = i, Result = o }); 
+1

+1 Có, vui vẻ thực sự. – sloth

+0

@Steven: Bạn sẽ sử dụng các kết quả mới này như thế nào? Bạn có một loại với cấu trúc tương ứng? – Jon

+0

Tôi sẽ DataBind kết quả vào GridView. Tôi đang cố gắng thêm một cột số hàng vào GridView. – Steven

2

Theo bạn chỉnh sửa 1. NO, BẠN KHÔNG THỂ LINQ trả về bảng như nó được. Bạn có thể xây dựng mỗi cột, nhưng bạn mất sức mạnh của các thực thể được ánh xạ.

này đã được hỏi nhiều lần trước đây: How do you add an index field to Linq results

1

Không có cách nào đơn giản nếu muốn giữ một danh sách phẳng của cột (ví dụ:Chỉnh sửa2 của OP) và cũng muốn có một giải pháp chung hoạt động với bất kỳ IEnumerable nào mà không yêu cầu bạn liệt kê ra các cột dự kiến. Tuy nhiên, có một cách vòng xoay để loại bỏ nó là đưa kết quả truy vấn vào một DataTable sử dụng phương thức ToDataTable() từ here và sau đó thêm cột RowNumber vào bảng đó.

var table = query.ToList().ToDataTable(); 
table.Columns.Add("RowNum", typeof(int)); 
int i = 0; 
foreach (DataRow row in table.Rows) 
    row["RowNum"] = ++i; 

Điều này có thể gây ra vấn đề về hiệu năng với bộ dữ liệu lớn nhưng cũng không quá chậm. Trên máy của tôi, một tập dữ liệu với ~ 6500 hàng mất 33ms để xử lý.

Nếu truy vấn ban đầu của bạn trả về một loại ẩn danh, thì định nghĩa kiểu đó sẽ bị mất trong chuyển đổi, do đó bạn sẽ mất đánh máy tĩnh trên tên cột của kết quả IEnumerable khi bạn gọi table.AsEnumerable(). Nói cách khác, thay vì có thể viết một cái gì đó như table.AsEnumerable(). Đầu tiên() RowNum bạn thay vì phải viết table.AsEnumerable(). First() ["RowNum"]

Tuy nhiên, nếu bạn không quan tâm đến hiệu suất và thực sự muốn gõ lại tĩnh, sau đó bạn có thể sử dụng JSON.NET để chuyển đổi DataTable thành chuỗi json và sau đó quay lại danh sách dựa trên loại ẩn danh từ kết quả truy vấn ban đầu. Phương thức này yêu cầu một trường giữ chỗ RowNum có mặt trong kết quả truy vấn ban đầu.

var query = (from currRow in someTable 
      where currRow.someCategory == someCategoryValue 
      orderby currRow.createdDate descending 
      select new { currRow.someCategory, currRow.createdDate, RowNum = -1 }).ToList(); 
var table = query.ToDataTable(); 
//Placeholder RowNum column has to already exist in query results 
//So not adding a new column, but merely populating it 
int i = 0; 
foreach (DataRow row in table.Rows) 
    row["RowNum"] = ++i; 
string json = JsonConvert.SerializeObject(table); 
var staticallyTypedList = JsonConvert.DeserializeAnonymousType(json, query); 
Console.WriteLine(staticallyTypedList.First().RowNum); 

Điều này đã thêm khoảng 120ms vào thời gian xử lý cho tập dữ liệu mục 6500 của tôi.

Thật điên rồ, nhưng nó hoạt động.

0

Tôi biết tôi đến muộn với bữa tiệc, nhưng tôi muốn thể hiện điều gì đã hiệu quả với tôi.

Tôi có một danh sách các đối tượng và đối tượng có thuộc tính số nguyên trên đó cho "số hàng" ... hoặc trong trường hợp này là "Số thứ tự". Đây là những gì tôi đã làm để điền vào trường đó:

myListOfObjects = myListOfObjects.Select((o, i) => { o.SequenceNumber = i; return o; }).ToList(); 

Tôi rất ngạc nhiên khi thấy điều này hiệu quả.