我想出了一个简单的例子,希望能够说明我的目标。我目前有一个方法,返回一种排序“排名”,它不是那么复杂,但它不会转换为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更感兴趣。
答案 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上找到一些很好的信息。