2012-03-30 15 views
5

mam kod jak następuje: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; 
.............. 
} 

Mam około 10-15 pól (jak „kod” i „nazwa”) i nie chcę, aby skopiować i wkleić kod z podobną tylko jeden różnica - nazwa pola.

Czy istnieje sposób generalizacji zapytania w jakiś sposób?

+0

Wiesz co jest zabawne? Mamy dokładnie ten kod w pracy, w klasie SortHelper wklejanej około 200 razy: |. Zainteresowany, aby zobaczyć, co się z tym stanie! +1 – mattytommo

Odpowiedz

7

Można użyć refleksji (zakładając code i name są właściwości, jeśli są one zmienne publiczne, musisz odpowiednio zmodyfikować):

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)); 

Jak Dunc wskazuje w komentarzach poniżej, że podejście to wymusza refleksję na każdym etapie wyliczenia, a refleksja jest kosztowna w miarę wykonywania operacji. Jeśli twoja kolekcja jest jednorodna, możesz osiągnąć lepszą wydajność poprzez przeniesienie odbicia z wyliczenia. Jeśli model zawiera tylko elementy typu Foo, można wykonać następujące zamiast:

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)); 

proszę, że to nie będzie rzucać TargetException jeśli kolekcja nie jest jednorodna.

+0

Przyjemna, mała sugestia co do wydajności: spróbuj przenieść x.GetType(). GetProperty (sort.Column) z wyrażenia LINQ, aby uniknąć powtórnego odbicia – Dunc

+0

Dobra sugestia, Dunc, uaktualnię odpowiednio moją odpowiedź. –

3

To by Cię zaczęło, ale możesz również użyć odbicia, aby uzyskać nazwę właściwości przez kolumnę, jeśli właściwość i kolumna są dokładnie dopasowane.

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

... code down to switch ... 

byłoby to skrócić swoje imię sprawę:

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

Ale z refleksji, można to zrobić bez przełącznika, ale jestem trochę słaby na refleksję, więc będę go opuścić komuś innemu, jeśli chcą.

1

Jak mówi "brak takiego adresu IP", istnieją wzorce do tego - dyspozytor poleceń/metoda fabryczna/itd. To są ważne wybory. Ale czasami mogą po prostu ukryć złożoność. Moją sugestią jest spojrzenie na użycie dynamicznego linq. Oto link do rozpoczęcia: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Możesz również rzucić własną, jeśli chcesz, ponieważ nie jest zbyt skomplikowana. Twórz własne metody rozszerzenia, które pozwalają przekazywać parametry (tj. Kierunek sortowania, kolumna sortowania) o zamówieniu oraz w ramach tej metody rozszerzenia, tworzyć własne zamówienie za pomocą instrukcji przy użyciu przestrzeni nazw system.linq.expressions. Oto przykład tego, jak dobrze: http://ronniediaz.com/2011/05/24/orderby-string-in-linq-c-net-dynamic-sorting-of-anonymous-types/

+0

Ładne rozwiązanie, wygląda na zdemontowane źródło C# zapytania LINQ. –