LINQ to Entities - 未识别方法
我正面临对Queryable数据集执行查询的问题。 原始呼叫看起来是这样的:LINQ to Entities - 未识别方法
books = books.Where(b => (GetPropertyValue(b, filter.CategoryProperties.DbName) == null ? 0 : Convert.ToInt32(GetPropertyValue(b, filter.CategoryProperties.DbName))) < Convert.ToInt32(filter.Value));
这让我的方法不承认错误。 这当然是由于对GetPropertyValue的调用所致。然后我读到我应该自己构建表达树。 导致下面的代码:
public IQueryable<Books> GetExpression(IQueryable<Books> books, BookCategoryMapping filter)
{
var booksExpression = Expression.Parameter(typeof(Books), "b");
var methodInfo = this.GetType().GetMethod("GetPropertyValue");
var value = Expression.Call(methodInfo, booksExpression, Expression.Constant(filter.CategoryProperties.DbName));
var left = Expression.Constant(value);
var right = Expression.Constant(filter.Value);
var expression = Expression.Equal(left, right);
var whereExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { books.ElementType }, books.Expression, Expression.Lambda<Func<Books, bool>>(expression, new ParameterExpression[] { booksExpression }));
return books.Provider.CreateQuery<Books>(whereExpression);
}
唯一的问题是,我得到了同样的错误。看起来下面一行只产生一个表达式而不是所述表达式的值。
var value = Expression.Call(methodInfo, booksExpression, Expression.Constant(filter.CategoryProperties.DbName));
任何产生正确的表达式树的帮助,将不胜感激:-)
编辑: 这里的GetPropertyValue方法:
public static object GetPropertyValue(object obj, string name)
{
try
{
return obj.GetType().GetProperty(name)?.GetValue(obj, null);
}
catch (Exception ex)
{
LogManager.Log(LogLevel.Error, null, ex);
}
return obj;
}
的方法,下面产生一个Expression<Func<Book, bool>>
,确定是否一给定Book
的属性小于给定(恒定)值。您目前在GetPropertyValue
中的错误检查代码可能可以通过捕获ArgumentException
来代替,当您尝试为不存在的属性创建表达式时将会抛出该代码。
请注意,我假定您正在访问的属性是真正的数字,并且您只需致电Convert.ToInt32
,因为您的GetPropertyValue
方法返回object
。
Expression<Func<Book, bool>> GenerateLessThanExpression(string propertyName, int value)
{
var parameter = Expression.Parameter(typeof (Book));
var property = Expression.Property(parameter, propertyName);
var comparison = Expression.LessThan(property, Expression.Constant(value));
return Expression.Lambda<Func<Book, bool>>(comparison, parameter);
}
下面是一个示例使用返回非常短的书:
var filter = GenerateLessThanExpression("Pages", 5);
var filtered = books.Where(filter);
我将添加一条评论。在Expression.LessThan我不得不解析一个类型作为第三个参数,否则我无法得到它的工作:-) –
你能澄清这一点?上面的代码用样本类进行测试,并按原样运行。你是什么类型的“解析”? –
我解析,property.Type,当然确保我比较它的值是相同的类型 –
你回答了你自己的问题:你不能在LINQ到实体查询中使用C#方法,因为的调用方法不能转换为SQL。如果让编译器构建表达式,或者如果自己构建表达式,它不会改变任何内容 - 它仍然不能转换为SQL。 – Maarten
我认为解决方案'自己构建表达式树“的意思就是:将方法'GetPropertyValue'的内容转换为表达式,以便**可以转换为SQL。目前,您将方法**的调用**转换为表达式树,但必须将整个方法**转换为表达式树。 – Maarten
您可以将“GetPropertyValue”方法添加到问题中吗? – Maarten