How to use a Func in an expression with Linq to Entity Framework?

為{幸葍}努か 提交于 2019-12-18 02:50:37

问题


I am trying to write a linq to entity extension method that takes a Func to select a property Id and compare it against a list of ids.

Classes

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

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

Extension Method

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

Calling Method

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

The problem I am experiencing is that it is trying to Invoke the function which is not allowed in Entity Framework.

How can I use a property selector (Func) to evaluate the query?


回答1:


You'll have to pass an Expression<Func<T, int>> instead of an Func<T, int> and build up the complete expression yourself. This will do the trick:

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

When you try to keep your code DRY when working with your O/RM, you will often have to fiddle with expression trees. Here's another fun example.



来源:https://stackoverflow.com/questions/19052507/how-to-use-a-func-in-an-expression-with-linq-to-entity-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!