【问题标题】:Combine OrderBy Expression with Where Expression将 OrderBy 表达式与 Where 表达式结合
【发布时间】:2012-06-14 17:08:52
【问题描述】:

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

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

我想知道如何使用类似的技术将 .OrderBy Expression<Func<Entity, Key>> 与 .Where Expression<Func<Entity, bool>> 合并为一个类型表达式,或从类型继承 System.Linq.Expressions.Expression。

我正在制作一个非常精简的 QueryProvider 样式类,用于通过公共方法 .Where 和 .OrderBy 获取 T => T == ... Func。这是为了将此类构建的表达式传递给 QueryTranslator 以创建合适的 SQL。

这种风格的 QueryTranslator,当从 QueryProvider 调用时,通常将 System.Linq.Expressions.Expression 作为参数,然后将其转换为 SQL。

我可以理解并理解上述合并两个.Where 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 组合时,两者具有不同的通用参数。在 .Where 的情况下是 Func<Entity, bool>,在 .OrderBy 的情况下是 Func<Entity, Key>。

从表面上看,合并这两个表达式并不像合并两个具有相同通用参数的表达式那么简单。

内置的 Func-Expression-production-engine(不确定确切的术语)能够将 .Where Func 与 .OrderBy Func 结合起来。我很好奇当这两个表达式合并为一个System.Linq.Expressions.Expression 时会发生什么。有可能吗,如果可以,假设每个表达式中的实体类型相同,您将如何将 Expression<Func<Entity, bool>> 与 Expression<Func<Entity,Key>> 组合?

【问题讨论】:

  • 生成的表达式应该是什么样子?
  • 应该和.Where(T=>T.Name=="Cooper").OrderBy(T=>T.DateOfBirth)一样
  • 您将.Where(x => condition1).Where(x => condition2) 合并到.Where(x => condition1 && condition),但您不能以同样的方式合并.Where(x => condition).OrderBy(x => value)。那么,再一次,结果表达式应该是什么样子? queryable.Where(x => condition).OrderBy(x => value) 不返回表达式,它返回 IQueryable<T>。
  • 不知道为什么这个问题被投票这么多。就目前而言,它没有意义,而且定义不足。
  • 道歉。更新了问题以提高清晰度。这里的 .Where 和 .OrderBy 总是与调用 .Where(Expression>) 或 .OrderBy(Expression) 时创建的表达式相关。这是关于组合调用这些方法后创建的表达式。

标签: c# linq expression linq-expressions


【解决方案1】:
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

【讨论】:

  • 我喜欢直截了当,但这并不是我所追求的。我没有可用的资源,所以没有什么可以用这种方式查询的。
【解决方案2】:

我认为这个问题之所以模棱两可,是因为它有点无法回答。

我试图构建一个超级表达式,例如 IQueryable&lt;&gt; 表达式构建器如何在一个表达式中使用 .Where 和 .OrderBy 表达式。

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

要将.Where 表达式与.OrderBy 表达式组合成一个表达式,您需要MethodCallExpression 来分隔两个LambdaExpression。

MethodCallExpression 需要一个主题来调用方法。这是使用IQueryable&lt;&gt; 的地方。

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

这与 IQueryable&lt;&gt; QueryProvider 不同,后者分析一个超级表达式并根据表达式中的 MethodCallExpression 将 SQL 输出到正确的位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    相关资源
    最近更新 更多