У меня есть следующий метод для создания некоторых пользовательских запросов EF для поддержки текстового фильтра, который очень близок к работе, но у меня возникла проблема с левой стороной собранного выражения.Когда я использую «Expression.Invoke» (первая строка тела метода), я получаю исключение, которое The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
, что имеет смысл для меня (я концептуально понимаю, что происходит в переводе LINQ => SQL).Поэтому я решил, что левой стороне выражения должно быть что-то более похожее на правую сторону (то есть с использованием Expression.Constant
), где выполняется вся «предварительная обработка», чтобы LINQ to Entities знал, как создать левую часть выражения.
Но когда я использую 2-ю строку (Expression.Property
), я получаю исключение:
Instance property 'PropertyName' is not defined for type System.Func2[Proj.EntityFramework.DomainObject,System.Decimal]'
Что я понимаю .... гораздо меньше.
Пример вызоварассматриваемый метод:
return context.DomainObjects.Where(BuildExpression(l => l.PropertyName, "<200"));
Итак, я примерно понимаю, что неправильно строю выражение и пытаюсь извлечь имя свойства из предоставленного выражения, а не того, что EF необходимо для компиляции оператора SQL, ноВ этот момент я немного растерялся.
private static Expression<Func<DomainObject, bool>> BuildExpression<TDest>(
Expression<Func<DomainObject, TDest>> propertyexpression,
string term
) where TDest : struct {
//var property = Expression.Invoke(propertyexpression, propertyexpression.Parameters.ToArray());
var property = Expression.Property(propertyexpression, ((MemberExpression)propertyexpression.Body).Member.Name);
var parser = new ParsedSearchTerm<TDest>(term); // e.g. "<200" => { LowerBound = null, Operator = "<", UpperBound = 200 }
Expression final = null;
if (parser.HasLowerBound) {
final = Expression.AndAlso(
Expression.GreaterThanOrEqual(property, Expression.Constant(parser.LowerBound)),
Expression.LessThanOrEqual(property, Expression.Constant(parser.UpperBound)));
}
else {
switch (parser.Operator) {
case "<":
final = Expression.LessThanOrEqual(property, Expression.Constant(parser.UpperBound));
break;
case ">":
final = Expression.GreaterThanOrEqual(property, Expression.Constant(parser.UpperBound));
break;
case "=":
final = Expression.Equal(property, Expression.Constant(parser.UpperBound));
break;
case "!":
final = Expression.Negate(Expression.Equal(property, Expression.Constant(parser.UpperBound)));
break;
}
}
return Expression.Lambda<Func<DomainObject, bool>>(final, propertyexpression.Parameters.ToArray());
}