在Linq中创建排序表达式方法

时间:2012-02-23 04:19:14

标签: c# linq c#-4.0

我想出了一个简单的例子,希望能够说明我的目标。我目前有一个方法,返回一种排序“排名”,它不是那么复杂,但它不会转换为SQL。性能很糟糕,因为它都是在内存中完成的,我正在努力提高速度。

public class Something
{
   DateTime Date {get; set;}
   // ...

   public int SortRank(Sort sort)
   {
     if (sort == Sort.Newest)
     {
       return -Date.Ticks;
     {
     else if (sort == sort.Oldest)
     {
       return Date.Ticks;
     }
   }
}

enum Sort
{
  Newest,
  Oldest
}

using (Context db = new Context()
{
  var q = db.GetTable<Something>()
            .OrderBy(x=> x.SortRank(Sort.Newest));
}

SortRank()目前没有转换为SQL,因此我想将其转换为Expression,以便可以在数据库中进行评估。做这个的最好方式是什么?是的,我知道我可以在匿名lambda中实现这个内联,但我对如何生成一个Expression更感兴趣。

1 个答案:

答案 0 :(得分:1)

我建议其他人建议你创建一个IOrderedQueryable。创建表达式(尤其是上面的表达式)非常简单。您可以查看OrderBy的参数,以了解如何构造它,它看起来像:

Expression<Func<Something, Date>> sortExpression = t => t.Date;

然后您可以像db.GetTable<Something>().OrderBy(sortExpression)一样使用它。因此,您可以看到如何轻松地创建不同的排序表达式。这就是说我仍然认为创建IOrderedQueryable的地方是最干净的,并且会产生最好的SQL查询。

public IOrderedQueryable<Something> SortRank(IQueryable<Something> query, Sort sort)
{
    Expression<Func<Something, DateTime>> sortExpression = t => t.Date;

    if (sort == Sort.Newest)
    {
        return query.OrderByDescending(sortExpression);
    }
    else
    {
        return query.OrderBy(sortExpression);
    }
}

您甚至可以将签名更改为

public static IOrderedQueryable<Something> SortRank(this IQueryable<Something> query, Sort sort) 

并将其用作扩展方法。

然后你可以这样称呼它:

using (Context db = new Context() 
{ 
    var q = SortRank(db.GetTable<Something>(), Sort.Newest); 
    //Extension method version
    var q = db.GetTable<Something>().SortRank(Sort.Newest);
} 

另一种选择是创建表达式树,将您的枚举直接翻译成查询,但这更复杂,我相信您可以在Google和SO上找到一些很好的信息。