9

Func を使用してプロパティ Id を選択し、それを ID のリストと比較するエンティティ拡張メソッドへの linq を作成しようとしています。

クラス

public class A
{
    public int AId { get; set; }
}

public class B
{
    public int BId { get; set; }
}

延長方法

public static IQueryable<T> WithId<T>(this IQueryable<T> entities,
    Func<T, int> selector, IList<int> ids)
    {
        Expression<Func<T, bool>> expression = x => ids.Contains(selector(x));
        return entities.Where(expression); // error here (when evaluated)
    }

呼び出し方法

var ids = new List<int> { 1, 2, 3 };
DbContext.EntityAs.WithId(e => e.AId, ids);
DbContext.EntityBs.WithId(e => e.BId, ids);

私が経験している問題は、Entity Framework で許可されていない関数を呼び出そうとしていることです。

プロパティ セレクター (Func) を使用してクエリを評価するにはどうすればよいですか?

4

1 に答える 1

20

Expression<Func<T, int>>an の代わりに anを渡して、Func<T, int>自分で完全な式を作成する必要があります。これはトリックを行います:

public static IQueryable<T> WithId<T>(this IQueryable<T> entities,
    Expression<Func<T, int>> propertySelector, ICollection<int> ids)
{
    var property =
        (PropertyInfo)((MemberExpression)propertySelector.Body).Member;

    ParameterExpression parameter = Expression.Parameter(typeof(T));

    var expression = Expression.Lambda<Func<T, bool>>(
        Expression.Call(
            Expression.Constant(ids),
            typeof(ICollection<int>).GetMethod("Contains"), 
            Expression.Property(parameter, property)), 
        parameter);

    return entities.Where(expression);
}

O/RM で作業するときにコードを DRY に保とうとすると、多くの場合、式ツリーをいじる必要があります。別の楽しい例を次に示します。

于 2013-09-27T14:30:28.980 に答える