2010-03-29 98 views
6

反正是有此代碼可重構?唯一的區別是按部分順序。LINQ查詢需要按升序或在同一個查詢降

Idealy我想這樣的代碼可以重複使用,但我不知道如何有條件地添加和刪除查詢運營商排序依據和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); 

回答

12

您可以創建自己的可重複使用的擴展方法,這將做到這一點:

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

,類似的還有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

很酷。謝謝喬恩。 – 2010-03-29 06:32:01

+0

有點偏題,但上面的代碼是否會正確轉換到Linq2SQL? IOW能夠在構建語法樹並生成SQL之前看到「不受支持」的方法並執行它,這足夠聰明嗎?只是想知道,從來沒有嘗試過。 :) – leppie 2010-03-29 06:34:28

+1

@leppie:這只是調用現有的Queryable方法 - 這些是構建表達式樹的。請注意,此*目前不適用於'IEnumerable ',但您可以輕鬆編寫等效的擴展方法。 – 2010-03-29 06:53:52

0

與數字等,以使用委託/ lambda表達式你通常可以否定'排序變量'。

隨着DateTime,我不是很確定。你可以嘗試使用Timespan

2

您最多可以拆分查詢到位,並使用控制流邏輯。 LINQ to SQL將奇蹟般地構建正確的查詢,就好像您已經將其全部輸入一行一樣!這樣做的原因是查詢在請求數據之前不會發送到數據庫,而是作爲表達式存儲。

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 !!!!!!!!!您的訂購需要在選擇之前發生,否則您處理不同的類型:) – leppie 2010-03-29 06:30:22

+0

感謝馬克。如果查詢操作符的順序放在select()之後,這有什麼關係嗎? – 2010-03-29 06:30:38

+0

@leppie:對,對不起,我沒注意到! – 2010-03-29 06:32:33

0

好了,如果你有一個條件,你決定是否爲了通過是升序或降序你可以使用這個

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

請參閱下面的答案,您犯了同樣的錯誤(現在已修復)。 – leppie 2010-03-29 06:35:48

+0

@leppie:不僅它是固定的,而且它現在在上面,不在下面。所以你的評論是不準確的,可能比有幫助的更混亂!爲什麼不重複你的評論,而不是嘗試使用參考?換句話說,只需寫下:'你的訂單需要在選擇之前發生,否則你處理不同的類型'。 ;-) – 2010-03-29 06:43:54

+0

在那裏,修復它。不過,我認爲我更喜歡jon的回答我自己;-) – 2010-03-29 07:01:38

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