2012-03-30 39 views
5

tôi có mã như sau:Entity Framework generic

switch(sort.Column) 
{ 
    case "code": 
    model = (sort.Direction == SortDirection.Ascending) 
      ? model.OrderBy(x => x.code) 
      : model.OrderByDescending(x => x.code); 
    break; 
    case "name": 
    model = (sort.Direction == SortDirection.Ascending) 
      ? model.OrderBy(x => x.name) 
      : model.OrderByDescending(x => x.name); 
    break; 
.............. 
} 

Tôi có khoảng 10-15 lĩnh vực (như 'mã' và 'tên') và tôi không muốn sao chép và dán mã tương tự với chỉ có một sự khác biệt - tên trường.

Có phương pháp tổng quát truy vấn bằng cách nào đó không?

+0

Bạn biết điều gì buồn cười không? Chúng tôi có mã chính xác này tại nơi làm việc, trong lớp SortHelper được dán khoảng 200 lần: |. Quan tâm để xem điều gì xảy ra với điều này! +1 – mattytommo

Trả lời

7

Bạn có thể sử dụng phản xạ (điều này giả định codename là tài sản, nếu họ là các biến công cộng, bạn sẽ phải thay đổi cho phù hợp):

model = (sort.Direction == SortDirection.Ascending) 
    ? model.OrderBy(x => x.GetType() 
     .GetProperty(sort.Column).GetValue(x, null)) : 
    : model.OrderByDescending(x => x.GetType() 
     .GetProperty(sort.Column).GetValue(x, null)); 

Như Dunc chỉ ra trong các ý kiến ​​dưới đây, cách tiếp cận này buộc phản ánh ở mỗi bước của điều tra, và sự phản ánh là tốn kém khi các hoạt động đi. Nếu bộ sưu tập của bạn là đồng nhất, bạn có thể đạt được hiệu suất tốt hơn bằng cách di chuyển phản xạ ra khỏi điều tra. Nếu model của bạn có chứa chỉ phần tử kiểu Foo, bạn có thể làm như sau thay vì:

var prop = typeof(Foo).GetProperty(sort.Column); 

model = (sort.Direction == SortDirection.Ascending) 
    ? model.OrderBy(x => prop.GetValue(x, null)) : 
    : model.OrderByDescending(x => prop.GetValue(x, null)); 

Xin lưu ý rằng điều này sẽ ném một TargetException nếu sưu tập của bạn là không đồng nhất.

+0

Đẹp, gợi ý hiệu suất nhỏ: cố gắng di chuyển x.GetType() GetProperty (sort.Column) ra khỏi biểu thức LINQ để tránh phản xạ lặp lại – Dunc

+0

Đề xuất tốt, Dunc, tôi sẽ cập nhật câu trả lời của mình cho phù hợp. –

3

Điều này sẽ giúp bạn bắt đầu, nhưng bạn cũng có thể sử dụng sự phản chiếu để lấy tên thuộc tính thông qua Cột, nếu thuộc tính và cột khớp chính xác.

// inline function 
Func<Func<Model, TResult>, Model> Order = criteria => 
{ 
    return (sort.Direction == SortDirection.Ascending) 
      ? model.OrderBy(criteria) 
      : model.OrderByDescending(criteria); 
} 

... code down to switch ... 

này sẽ rút ngắn trường hợp tên của bạn để:

model = Order(x => x.name); 

Nhưng với phản ánh, bạn có thể làm điều đó mà không cần chuyển đổi, nhưng tôi là một chút yếu trên phản ánh, vì vậy tôi sẽ để nó cho người khác nếu họ muốn.

1

Vì 'Không có IP như vậy' cho biết, có các mẫu cho lệnh này - lệnh điều phối/phương pháp nhà máy/v.v. Đó là những lựa chọn hợp lệ. Nhưng đôi khi những điều này chỉ có thể che giấu sự phức tạp. Đề xuất của tôi là xem xét sử dụng LINQ động. Đây là một liên kết để bạn bắt đầu: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Bạn cũng có thể tự mình cuộn nếu bạn muốn vì nó không quá phức tạp. Tạo các phương thức mở rộng của riêng bạn cho phép bạn chuyển các tham số (tức là sắp xếp hướng, sắp xếp cột) về thứ tự của bạn và trong phương thức mở rộng đó, xây dựng thứ tự của riêng bạn bằng câu lệnh bằng cách sử dụng không gian tên system.linq.expressions. Dưới đây là một ví dụ về điều đó cũng như: http://ronniediaz.com/2011/05/24/orderby-string-in-linq-c-net-dynamic-sorting-of-anonymous-types/

+0

Giải pháp hay, trông giống như nguồn C# của các truy vấn LINQ. –