2012-11-21 36 views
8

Tôi có một giao diện báo cáo trong đó người dùng cuối sẽ chọn nhiều trường cho thứ tự sắp xếp của báo cáo được trả về. Vấn đề tôi gặp phải là tôi không thể thực sự chuỗi các phương thức OrderBy/ThenBy, vì tôi đang lặp qua một danh sách các trường sắp xếp. Tôi đang nghĩ đến một cái gì đó như thế này:Lập trình chuỗi OrderBy/ThenBy sử dụng LINQ/Entity Framework

foreach (string sort in data.SortParams) 
{ 
    switch (sort) 
    { 
     case "state": 
      query = query.ThenBy(l => l.RegionCode); 
      break; 
     case "type": 
      query = query.ThenBy(l => l.Type); 
      break; 
     case "color": 
      query = query.ThenBy(l => l.Color); 
      break; 
     case "category": 
      query = query.OrderBy(l => l.Category); 
      break; 
    } 
} 

(Lưu ý:. Tôi đã gỡ bỏ công tắc xác định nếu điều này là mục trước sắp xếp để đơn giản)

Bất kỳ suy nghĩ về làm thế nào để lặp qua một bộ sưu tập để xác định thứ tự sắp xếp?

Trả lời

15

Bạn có thể làm những gì bạn muốn nếu bạn sử dụng một ban đầu "hạt giống" OrderBy:

EDIT bạn cần phải gọi OrderBy để tạo ra một IOrderedEnumerable (hoặc IOrderedQueryable) đầu tiên trước khi gắn ThenBy khoản:

var orderedQuery = query.OrderBy(l => 0); 
foreach (string sort in data.SortParams) 
{ 
    switch (sort) 
    { 
     case "state": 
      orderedQuery = orderedQuery.ThenBy(l => l.RegionCode); 
      break; 
     case "type": 
      orderedQuery = orderedQuery.ThenBy(l => l.Type); 
      break; 
     case "color": 
      orderedQuery = orderedQuery.ThenBy(l => l.Color); 
      break; 
     case "category": 
      orderedQuery = orderedQuery.ThenBy(l => l.Category); 
      break; 
    } 
} 
query = orderedQuery; // cast back to original type. 

Nếu bạn muốn điều gì đó linh hoạt hơn, hãy kiểm tra this answer

+0

Quảng cáo, nhưng cần phải kiểm tra xem điều này có ảnh hưởng đến hiệu suất truy vấn hay không. Nó có thể ngăn chặn việc sử dụng chỉ mục. – usr

+1

Điều này làm việc như một sự quyến rũ đối với tôi. Lúc đầu, tôi đã có chính xác mã tương tự như trên, tuy nhiên tôi đã buộc phải chọn một cột mặc định cho 'OrderBy() đầu tiên' - Tôi không biết tôi có thể đặt 0 ở đó để thay thế. Số 0 sẽ làm cho truy vấn SQL cuối cùng xuất hiện với cột phụ có giá trị 0 cho mỗi hàng, sau đó nó sắp xếp theo hàng đó, đạt được phân loại giả, sau đó nó áp dụng tất cả các cột trong chuỗi 'ThenBy() ' 'mà bạn đã thêm. Cảm ơn! – BeemerGuy

+0

Tôi nhận được 'ArgumentOutOfRangeException' khi gọi' OrderBy (l => 0) '. [Ở đây] (https://pastebin.com/raw/TZQ9g8Es) là 'StackTrace'. – Shimmy

-1

Có thể sử dụng tất cả trong một truy vấn LINQ không phải là lựa chọn tốt nhất từ ​​điểm dễ đọc. Tôi sẽ sử dụng IQueryable để xây dựng truy vấn của bạn trong bộ nhớ. Sử dụng loại lệnh chuyển đổi tương tự (nhưng với IQueryable) và sau đó cuối cùng làm .ToList (tức là liệt kê) để thực thi truy vấn mong muốn tại máy chủ.

+1

Cảm ơn, nhưng 'truy vấn' var ở đây thực chất là một IQueryable; vấn đề là với các lệnh OrderBy và ThenBy .. Có vẻ như nếu ThenBy chỉ có thể được sử dụng khi lần đầu tiên bị xích vào một OrderBy. – acullen72

+1

Chăm sóc expalin về bỏ phiếu xuống !! ???????? – daehaai

1

Tôi đã tạo các tiện ích này phương pháp để giải quyết một vấn đề giống hệt như đã nêu trong câu hỏi:

public static class QueryableExtensions 
{ 
    public static IOrderedQueryable<T> AppendOrderBy<T, TKey>(this IQueryable<T> query, Expression<Func<T, TKey>> keySelector) 
     => query.Expression.Type == typeof(IOrderedQueryable<T>) 
     ? ((IOrderedQueryable<T>) query).ThenBy(keySelector) 
     : query.OrderBy(keySelector); 

    public static IOrderedQueryable<T> AppendOrderByDescending<T, TKey>(this IQueryable<T> query, Expression<Func<T, TKey>> keySelector) 
     => query.Expression.Type == typeof(IOrderedQueryable<T>) 
      ? ((IOrderedQueryable<T>)query).ThenByDescending(keySelector) 
      : query.OrderByDescending(keySelector); 
} 

Mã trong câu hỏi có thể sau đó được refactored để:

foreach (string sort in data.SortParams) 
{ 
    switch (sort) 
    { 
     case "state": 
      query = query.AppendOrderBy(l => l.RegionCode); 
      break; 
     case "type": 
      query = query.AppendOrderBy(l => l.Type); 
      break; 
     case "color": 
      query = query.AppendOrderBy(l => l.Color); 
      break; 
     case "category": 
      query = query.AppendOrderBy(l => l.Category); 
      break; 
    } 
} 

REMARK Những phương pháp khuyến nông chỉ kiểm tra các biểu hiện trước đó trong cây biểu thức để xác định thời tiết sử dụng OrderBy hoặc ThenBy, không cho phép biểu thức nào khác ở giữa. Nếu bạn cũng muốn giải quyết điều đó, bạn sẽ phải đi qua cái cây hoàn chỉnh mà chỉ cần thêm vào cái mà bạn không muốn :)

Các vấn đề liên quan