将OrderBy表达式与Where表达式结合起来

时间:2012-06-14 17:08:52

标签: c# linq expression linq-expressions

我发现以下问题可以合并多个Expression<Func<T,bool>>表达式:

How to merge two C# Lambda Expressions without an invoke?

我想知道是否使用类似的技术,如何将.OrderBy Expression<Func<Entity, Key>>与。{{{{}}合并为一个类型的表达式,或继承自类型{{1 }}

我正在制作一个真正减少的QueryProvider风格的类,用于通过公共方法Expression<Func<Entity, bool>>System.Linq.Expressions.Expression获取T => T == ... Func。这是为了将此类构建的表达式传递给QueryTranslator以创建合适的SQL。

这种样式的QueryTranslator,当从QueryProvider调用时,通常会将一个.Where作为参数,然后转换为SQL。

我可以跟进并理解上面的问题,即合并两个.OrderBy Funcs。以下博客文章对此特别有用,我追溯了每个示例:

http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx

此CodeProject文章也很有用:

http://www.codeproject.com/Articles/24255/Exploring-Lambda-Expression-in-C

当.OrderBy Func与.Where Func组合时,两者有不同的泛型参数。如果是{。{1}},那么.OrderBy就是System.Linq.Expressions.Expression

从表面上看,合并这两个表达式并不像使用相同的泛型参数合并两个表达式那样简单。

内置的Func-Expression生成引擎(不确定术语)能够将.Where Func与.OrderBy Func结合起来。当这两个表达式合并成一个.Where时,我很好奇发生了什么。是否可能,如果是这样,如果假设每个表达式中的实体属性相同,您会如何将Func<Entity, bool>Func<Entity, Key>结合起来?

2 个答案:

答案 0 :(得分:3)

public IQueryable<T> ApplyExpressions<T, TKey>(
  Expression<Func<T, TKey>> sortBy,
  Expression<Func<T, bool>> filterBy,
  IQueryable<T> source)
{
  return source.Where(filterBy).OrderBy(sortBy);
}


IQueryable<Customer> query = ApplyExpressions<Customer, int>(
  c => c.Age,
  c => c.Name.StartsWith("B"),
  myDC.Customers)

Expression queryExpression = query.Expression;  //tada

答案 1 :(得分:0)

我认为这个问题含糊不清是因为它有点无法回答。

我正在尝试构建一个超级表达式,就像IQueryable<>表达式构建器如何在一个表达式中使用.Where.OrderBy表达式一样。

然而,如果没有主题,我对表达式和表达式树的有限理解似乎表明它是不可能的。

要将.Where表达式与.OrderBy表达式合并到一个表达式中,您需要MethodCallExpression来分隔两个LambdaExpression

MethodCallExpression需要主题调用方法。这是使用IQueryable<>的地方。

我更改了我的Query类以使所有LambdaExpression分开,然后将它们分别传递给QueryTranslator。 QT将输出SQL合并到正确的位置。

这与IQueryable<> QueryProvider相反,后者分析一个超级表达式,并根据表达式中的MethodCallExpression将SQL输出到正确的位置。