使用表达式树为EF4动态构建查询,NotSupportedException
本文关键字:构建 查询 NotSupportedException 动态 EF4 表达式 | 更新日期: 2023-09-27 18:21:22
我正试图构建一个表达式树,以便在带有EF4的.NET 4.0中执行LINQ to Entities查询。当我尝试执行我构建的查询时,我会得到一个NotSupportedException
,其中包含以下消息:
LINQ to Entities无法识别该方法'System.Data.Objects.ObjectQuery`1[TestWpf.Customer]Where(System.String,System.Data.Objects.ObjectParameter[])'方法,并且该方法不能被翻译成存储表达式。
我正在查询Northwind数据库。我的实体是从数据库中生成的。在下面的代码中,我有一个查询,我正试图用方法GetQuery1()
构建它,我正尝试用GetQuery2()
方法构建它。
如果我设置了一个断点并检查query1
变量,它的Expression
属性是:
Convert(value(System.Data.Objects.ObjectSet`1[TestWpf.Customer])).MergeAs(AppendOnly).Where(c => c.CompanyName.Contains("z"))
这个Convert().MergeAs(AppendOnly)
在干什么?我试图在MSDN上搜索,但找不到我需要的东西(至少我认为我找不到…)。此外,我做错了什么?
我想,也许我调用了一个不正确的Where()
方法,正如Intellisense所说,还有另一个方法,那就是扩展方法。我还没有尝试更新whereMethod
变量来获取该变量,但我也不确定如何更新。
private static IQueryable<Customer> GetQuery1(NorthEntities context) {
return context.Customers.Where(c => c.CompanyName.Contains("z"));
}
private static IQueryable<Customer> GetQuery2(NorthEntities context) {
var custParam = Expression.Parameter(typeof(Customer), "c");
var custCollection = Expression.Constant(context.Customers);
var companyNamePropValue = Expression.Property(custParam, typeof(Customer).GetProperty("CompanyName"));
var containsParameter = Expression.Constant("z");
var containsMethod = Expression.Call(companyNamePropValue, typeof(string).GetMethod("Contains"), containsParameter);
var whereMethod = context.Customers.GetType().GetMethod("Where", new Type[] { typeof(string), typeof(ObjectParameter[]) });
var param2 = Expression.Constant(new ObjectParameter[] { });
var where = Expression.Call(custCollection, whereMethod, companyNamePropValue, param2);
return ((IQueryable<Customer>)context.Customers).Provider.CreateQuery<Customer>(where);
}
private static void Main(string[] args) {
using (var context = new NorthEntities()) {
var query1 = GetQuery1(context);
var query2 = GetQuery2(context);
foreach (var c in query1)
Console.WriteLine(c.CompanyName);
foreach (var c in query2)
Console.WriteLine(c.CompanyName);
}
Console.ReadLine();
}
要构建您正在使用的特定查询,请尝试以下操作:
private static IQueryable<Customer> GetQuery2(NorthEntities context) {
IQueryable<Customer> customers = context.Customers;
var custParam = Expression.Parameter(typeof(Customer), "c");
var companyNamePropValue = Expression.Property(custParam, typeof(Customer).GetProperty("CompanyName"));
var containsParameter = Expression.Constant("z");
var containsCall = Expression.Call(companyNamePropValue, typeof(string).GetMethod("Contains"), containsParameter);
var wherePredicate = Expression.Lambda<Func<Customer, bool>>(containsCall, custParam);
return customers.Where(wherePredicate);
}
通常,要访问LINQ扩展方法(例如Where),您必须查看Queryable
类:
var genericWhereMethod = typeof(Queryable).GetMethods()
.Single(m => m.Name == "Where"
// distinguishes between Where((T, int) => bool) and Where(T => bool)
&& m.GetParameters()[1].ParameterType
.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Func<,>));
// make the Where method that applies to IQueryable<Customer>
var whereMethod = genericWhereMethod.MakeGenericMethod(typeof(Customer));