13

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

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

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

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

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

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

任何帮助是极大的赞赏。

4

1 回答 1

18

调用扩展方法,如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<T>,您需要将其汇总到一个方法中:

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;
}

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

于 2013-03-12T17:38:36.790 回答