构建IQueryable.Any与表达式树的LINQ查询(Build IQueryable.Any

2019-08-17 13:11发布

我建立一个SQL“WHERE”条款动态使用System.Linq.Expressions.Expression类。 它非常适用简单的条款,如加上“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))

不过,我似乎无法找到一种方式来表达与表达类。 实际上有两件事情我想不通:

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

任何帮助是极大的赞赏。

Answer 1:

调用扩展方法,像Enumerable.Any或Queryable.Any ,简直是在序列和你所创建的lambda表达式静态方法调用WHERE子句。 您可以使用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;
}

尽管这似乎很奇怪,你是无法通过正常的查询来做到这一点。



文章来源: Build IQueryable.Any with Expression Trees for LINQ queries