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

I am trying to write a linq extension method for entities that accepts Func to select a property identifier and compare it with a list of identifiers.

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

Call 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'm experiencing is that it is trying to call a function that is not allowed in the Entity Framework.

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

+6
source share
1 answer

You need to pass Expression<Func<T, int>> instead of Func<T, int> and create the full 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 save DRY code while working with your O / RM, you often have to deal with expression trees. Here 's another fun example .

+15
source

Source: https://habr.com/ru/post/954784/