1

我試圖構建一個表達式樹來執行LINQ to Entities在.NET 4.0與EF4查詢。當我嘗試執行我已經建立了查詢,我得到了NotSupportedException以下消息:動態構建使用表達式樹的查詢EF4,NotSupportedException

LINQ到實體無法識別方法 「System.Data.Objects.ObjectQuery`1 [TestWpf.Customer ] 其中(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(); 
} 

回答

1

構建你正在使用的特定查詢,請嘗試以下操作:

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)); 
+0

作品像一個魅力,謝謝。我也確定,我不需要在我的樹中包含'Where()'調用,只需要包含條件。第一次和他們一起工作,他們是混亂的! – Steve