我的课程DropdownFilter
有:
private readonly Func<TEntity, string> fieldWhichMustEqualValue;
public override IQueryable<TEntity> Filter(IQueryable<TEntity> filteredEntityCollection, string value)
{
return filteredEntityCollection.Where(entity => this.fieldWhichMustEqualValue(entity) == value);
}
我用它作为:
IQueryable<Invoice> entityCollectionToFilterAndOrder = ...
var dropdownFilter = new DropdownFilter<Invoice>(invoice => invoice.SomeProperty);
entityCollectionToFilterAndOrder = dropdownFilter.Filter(entityCollectionToFilterAndOrder, "bla bla bla");
给了我
LINQ表达式节点类型&#39;调用&#39; LINQ不支持 实体。
我理解问题是我基本上要求等同于Invoke
的SQL,这当然是错误的。
我应该如何重写代码?我明白它需要是一种表达方式。我的目标是DropDownFilter
的使用者只需指定TEntity
的属性,而不提供表达式。即表达式必须封装在过滤器中。
我试过了:
Expression<Func<TEntity, string>> expr = mc => this.fieldWhichMustEqualValue(mc);
Expression le = Expression.Equal(expr.Body, Expression.Constant(value));
var lambda = Expression.Lambda<Func<TEntity, bool>>(le, expr.Parameters);
return filteredEntityCollection.Where(lambda);
但它基本上给了我相同的结果。
答案 0 :(得分:0)
Func<TEntity, string>
是一个C#函数,因此无法在SQL服务器中执行。但是,如果将其更改为表达式,则可以起作用:
private readonly Expression<Func<TEntity, string>> fieldWhichMustEqualValue;
但是,现在Filter
函数无法编译,因为您无法调用表达式。你需要做的是撰写一个新的表达式:
public static UnaryExpression WrapInPropertyAccess(this ConstantExpression constant) {
Tuple<object> container = new Tuple<object>(constant.Value);
Expression containerExpression = Expression.Constant(container, typeof(Tuple<object>));
MemberExpression propAccess = Expression.Property(containerExpression, "Item1");
UnaryExpression result = Expression.Convert(propAccess, constant.Type); // Cast back the object to the value type
return result;
}
private Expression<TEntity, bool> FieldEqualsValue(string value) {
var comparison = Expression.Equal(fieldWhichMustEqualValue.Body, Expression.Constant(value).WrapInPropertyAccess());
return Expression.Lambda<Func<TEntity, bool>>(comparison, fieldWhichMustEqualValue.Parameters);
}
public override IQueryable<TEntity> Filter(IQueryable<TEntity> filteredEntityCollection, string value)
{
var condition = FieldEqualsValue(value);
return filteredEntityCollection.Where(condition);
}
WrapInPropertyAccess
函数不是严格需要的,但使用它会使Entity Framework生成参数化表达式。