2010-03-29 7 views
6

Czy mimo to ten kod może zostać refaktoryzowany? Jedyną różnicą jest kolejność po części.Zapytanie LINQ wymaga albo rosnącej, albo malejącej w tym samym zapytaniu.

Idealy Chciałbym użyć wyrażenia delegat/lambda więc kod jest wielokrotnego użytku, ale nie wiem jak warunkowo dodać lub usunąć orderby operatorów zapytań i OrderByDescending

var linq = new NorthwindDataContext(); 

     var query1 = linq.Customers 
      .Where(c => c.ContactName.StartsWith("a")) 
      .SelectMany(cus=>cus.Orders) 
      .OrderBy(ord => ord.OrderDate) 
      .Select(ord => ord.CustomerID); 

     var query2 = linq.Customers 
      .Where(c => c.ContactName.StartsWith("a")) 
      .SelectMany(cus => cus.Orders) 
      .OrderByDescending(ord => ord.OrderDate) 
      .Select(ord => ord.CustomerID); 

Odpowiedz

12

Można tworzyć własne wielokrotnego użytku metodę rozszerzenia, które będzie to zrobić:

public static IOrderedQueryable<TSource> OrderBy<TSource, TKey> 
    (this IQueryable<TSource> source, 
    Expression<Func<TSource, TKey>> keySelector, 
    bool ascending) 
{ 
    return ascending ? source.OrderBy(keySelector) 
      : source.OrderByDescending(keySelector); 
} 

i podobnie dla ThenBy:

public static IOrderedQueryable<TSource> ThenBy<TSource, TKey> 
    (this IOrderedQueryable<TSource> source, 
    Expression<Func<TSource, TKey>> keySelector, 
    bool ascending) 
{ 
    return ascending ? source.ThenBy(keySelector) 
      : source.ThenByDescending(keySelector); 
} 
+0

Fajnie. Dzięki Jon. –

+0

Wyłączyć temat, ale czy powyższe tłumaczenie zostanie poprawnie przetłumaczone na Linq2SQL? IOW jest na tyle sprytny, aby zobaczyć "nieobsługiwaną" metodę i wykonać ją przed zbudowaniem drzewa składni i wygenerowaniem kodu SQL? Zastanawiam się, nigdy tego nie próbowałem. :) – leppie

+1

@leppie: To po prostu wywołanie istniejących metod Queryable - to one budują drzewo wyrażeń. Zauważ, że to * nie * będzie działało przeciwko 'IEnumerable ' w tej chwili, chociaż możesz łatwo napisać równoważne metody rozszerzania, które by. –

0

z numerami, etc zwykle można po prostu zanegować "zmienną zamawiania".

Z DateTime, nie jestem tego taki pewien. Możesz spróbować użyć urządzenia Timespan.

2

Możesz podzielić zapytania na bity i użyć logiki przepływu sterowania. LINQ do SQL będzie magicznie konstruować poprawne zapytanie tak, jakbyś wpisał je wszystkie w jedną linię! Powodem tego jest to, że zapytanie nie jest wysyłane do bazy danych, dopóki nie zażądasz danych, ale zamiast tego zostanie zapisane jako wyrażenie.

var linq = new NorthwindDataContext(); 
var query = linq.Customers 
    .Where(c => c.ContactName.StartsWith("a")) 
    .SelectMany(cus=>cus.Orders); 

IOrderedQueryable<Order> query2; 
if (useAscending) { 
    query2 = query.OrderBy(ord => ord.OrderDate); 
} else { 
    query2 = query.OrderByDescending(ord => ord.OrderDate); 
} 

var query3 = query2.Select(ord => ord.CustomerID); 
+0

Errorrr !!!!!!!!! Twoje zamówienie musi się wydarzyć przed wyborem, w przeciwnym razie masz do czynienia z innym typem :) – leppie

+0

Dzięki Mark. Czy ma znaczenie, czy kolejność przez operatorów zapytań jest umieszczana po select()? –

+0

@leppie: Tak, przykro mi, że tego nie zauważyłem! –

0

dobrze, jeśli masz stan, w którym zdecydujesz jeśli zamówienie przez to rosnąco lub malejąco można użyć tego

var query1 = linq.Customers 
.Where(c => c.ContactName.StartsWith("a")) 
.SelectMany(cus=>cus.Orders) 

if(SortAscending) 
    query1 = query1.OrderBy(ord => ord.OrderDate); 
else 
    query1 = query1.OrderByDescending(ord => ord.OrderDate); 

var query2 = query1.Select(ord => ord.CustomerID); 
+0

Zobacz, popełniłeś ten sam błąd, co poniższa odpowiedź (jest teraz naprawiona). – leppie

+0

@leppie: Naprawiono to nie tylko teraz, ale także powyżej. Twój komentarz jest niedokładny i prawdopodobnie bardziej zagmatwany niż pomocny! Dlaczego po prostu powtórzyć swój komentarz, zamiast próbować użyć odniesienia? Innymi słowy, po prostu napisz to: "Twoje zamówienie musi się wydarzyć przed wyborem, w innym przypadku masz do czynienia z innym typem". ;-) –

+0

Naprawiono. Myślę jednak, że wolę odpowiedź od samego siebie ;-) –

1
return from T in bk.anbarsabts 
     where T.kalaname == str 
     orderby T.date descending 
     select new { T.date, T.kalaname, T.model, T.tedad }; 
Powiązane problemy