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

ただし、プロジェクトが特定のグループに割り当てられている場合にレコードを返す式を作成しようとしています。プロジェクトとグループには多対多の関係があります。式ツリーがなければ、次のようにします。

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

しかし、それを Expression クラスで表現する方法が見つからないようです。実際、私が理解できないことが2つあります。

  • テーブル間のリレーションシップをトラバースする方法
  • x.Any() の実行方法

どんな助けでも大歓迎です。

4

1 に答える 1

18

Enumerable.AnyQueryable.Anyなどの拡張メソッドの呼び出しは、シーケンスに対する静的メソッド呼び出しと、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;
}

これは奇妙に思えますが、通常のクエリではこれを行うことができません。

于 2013-03-12T17:38:36.790 に答える