【问题标题】:Build IQueryable.Any with Expression Trees for LINQ queries使用表达式树为 LINQ 查询构建 IQueryable.Any
【发布时间】:2013-03-12 17:29:43
【问题描述】:

我正在使用 System.Linq.Expressions.Expression 类动态构建 SQL“WHERE”子句。它适用于简单的子句,例如要添加“PhaseCode = X”子句,我执行以下操作:

var equalTarget = Expression.Constant(phaseCode, typeof(int?));
var phaseEquals = Expression.Equal(Expression.PropertyOrField(projParam, "PhaseCode"), equalTarget);

但是,现在我正在尝试构建一个表达式,如果项目已分配给特定组,则该表达式将返回记录。项目和组具有多对多的关系。 如果没有表达式树,我会这样做:

db.Projects.Where(p => .... && p.GroupsAssigned.Any(g => g.ID == groupId))

但是,我似乎找不到使用 Expression 类来表达这一点的方法。 实际上有两件事我想不通:

  • 如何遍历表之间的关系
  • 如何做 x.Any()

非常感谢任何帮助。

【问题讨论】:

    标签: c# expression-trees


    【解决方案1】:

    调用扩展方法,如Enumerable.AnyQueryable.Any,只是对序列和您为WHERE 子句创建的lambda 表达式的静态方法调用。您可以使用Expression.Call 来执行此操作:

    // for Enumerable.Any<T>(IEnumerable<T>,Predicate<T>)
    var overload = typeof(Enumerable).GetMethods("Any")
                                     .Single(mi => mi.GetParameters().Count() == 2);
    var call = Expression.Call(
        overload,
        Expression.PropertyOrField(projParam, "GroupsAssigned"),
        anyLambda);      
    

    对于Queryable.Any&lt;T&gt;,您需要将其汇总到一个方法中:

    static Expression BuildAny<TSource>(Expression<Func<TSource, bool>> predicate)
    {
        var overload = typeof(Queryable).GetMethods("Any")
                                  .Single(mi => mi.GetParameters().Count() == 2);
        var call = Expression.Call(
            overload,
            Expression.PropertyOrField(projParam, "GroupsAssigned"),
            predicate);   
    
        return call;
    }
    

    虽然这看起来很奇怪,但您无法通过正常查询来做到这一点。

    【讨论】:

    • 感谢您的解决方案,六个字母变量。 Expression.Call() 正是我所需要的。为了回答您的问题,在这种情况下我无法进行正常查询,因为在编译时我不知道我的 WHERE 语句中有多少 AND 部分。这完全取决于用户在搜索表单中所做的选择。构造表达式树似乎是唯一有效的解决方案。
    • 感谢上帝我看到了这个,我的错误是我打电话给typeof(Queryable).GetMethods("Any").Single(mi =&gt; mi.GetParameters().Count() == 2);而不是:typeof(Enumerable).GetMethods("Any").Single(mi =&gt; mi.GetParameters().Count() == 2);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多