Dav*_*vid 7 c# linq expression entity-framework func
我正在尝试将linq写入实体扩展方法,该方法使用Func选择属性Id并将其与ID列表进行比较.
类
public class A
{
public int AId { get; set; }
}
public class B
{
public int BId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
扩展方法
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)
}
Run Code Online (Sandbox Code Playgroud)
呼叫方法
var ids = new List<int> { 1, 2, 3 };
DbContext.EntityAs.WithId(e => e.AId, ids);
DbContext.EntityBs.WithId(e => e.BId, ids);
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是它试图调用Entity Framework中不允许的功能.
如何使用属性选择器(Func)来评估查询?
Ste*_*ven 16
你必须传递一个Expression<Func<T, int>>而不是一个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);
}
Run Code Online (Sandbox Code Playgroud)
当您在使用O/RM时尝试将代码保持干燥时,通常需要摆弄表达式树.这是另一个有趣的例子.