2010-03-29 90 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 };