2011-05-01 494 views
10

我有那些方法:LINQ到實體無法識別方法

public int count(
     Guid companyId, Expression<Func<T, bool>> isMatch) 
    { 
     var filters = new Expression<Func<T, bool>>[]{ 
      x => x.PriceDefinition.CompanyId == companyId, 
      isMatch 
     }; 

     return GetCount(filters); 
    } 

public virtual int GetCount(
      IEnumerable<Expression<Func<T, bool>>> filters) 
     { 
      IQueryable<T> _query = ObjectSet; 

      if (filters != null) 
      { 
       foreach (var filter in filters) 
       { 
        _query = _query.Where(filter); 
       } 
      } 

      return _query.Count(); 
     } 

使用:

count(some_guid, x => x.IsMatch(entityId, inviterId, routeId, luggageTypeId)); 

我得到以下異常:

LINQ to Entities does not recognize the method 'Boolean IsMatch(System.Nullable`1[System.Int64], System.Nullable`1[System.Int64], System.Nullable`1[System.Int64], System.Nullable`1[System.Int64])' method, and this method cannot be translated into a store expression. 

什麼這是爲什麼?
我該如何解決?

+0

你的過濾器是什麼? – SLaks 2011-05-01 02:27:14

+0

@ SLaks♦:對不起,我用isMatch委託更新了問題。 – Naor 2011-05-01 02:29:07

回答

14

當使用LINQ到實體不能使用查詢任意.NET方法。查詢中使用的每種方法都必須可轉換爲SQL。它不會幫助您返回Expession<Func<entityType, bool>>,因爲必須針對數據庫服務器上的每條記錄評估條件。

對於EF代碼是指這樣的:

SELECT COUNT(*) 
FROM ... 
LEFT JOIN ... 
WHERE IsMatch(....) 

由於EF驗證傳遞給查詢會拋出異常,因爲它不知道IsMatch相當於SQL服務器上的功能名稱。

,其可以用在LINQ到實體的唯一可能的功能是:

EdmFunctions都方法標有EdmFunctionAttribute其將.NET函數映射到SQL對應項。這些函數通常不能用通用的.NET代碼執行,因爲它們什麼都不做或拋出異常。他們只是Linq-to-entities的功能佔位符。可用EdmFunctions是:

  • 預定義EdmFunctions在System.Data.Objects.EntityFunctions
  • 預定義EdmFunctions在System.Data.Objects.SqlClient.SqlFunctions
  • SQL服務器(不緊湊)自定義映射SQL函數 - 在實體設計導入嚮導,可以導入SQL函數(除表值功能)。您可以在此之後編寫自定義靜態.NET函數,並將其按EdmFunction屬性映射到導入到設計器的SQL函數。
  • 自定義模型定義函數 - 這是在EDMX文件中手動編寫的特殊函數(以XML打開)。它是Entity SQL的自定義可重用部分。

我已經在另一個答案中描述了how to create model defined function。創建映射SQL function is pretty similar。而不是在EDMX中手動創建Function元素,而是將EdmFunctionAttribute屬性映射到導入的SQL函數。

2

您正在傳遞一個調用名爲IsMatch的函數的表達式。

LINQ to Entities不知道如何處理此功能。

+0

♦:我更新了問題.. – Naor 2011-05-01 02:29:44

+0

LINQ to Entities不知道如何將IsMatch轉換爲SQL。您需要用表達式樹替換它。 – SLaks 2011-05-01 02:31:19

+3

♦:「用表達式樹替換它」是什麼意思? – Naor 2011-05-01 02:34:18

1

我正在處理類似的問題。在嘗試使用我的自定義方法之前,工作解決方案使用了.AsEnumerable()。您可以take a look at it here

+0

添加AsEnumerable會將整個表加載到內存中,在companyId的過濾器之後,我仍然有很多結果。 – Naor 2011-05-01 02:42:33

+0

@Naor:好吧,它對我有用,因爲我工作的結果很少。不知道你的。 – Damb 2011-05-01 02:53:15

0

Actualy,要傳遞什麼指望像這樣的功能:

bool anonymous_delagate#123(T entity) 
{ 
    return entity.IsMatch(a,b,c,d) 
} 

但是,這需要EF知道,真正的方法IsMatch,被稱爲本實體,意味着。

我現在所能想到的只是使用某種動態表達式鍛造來創建查詢動態。或者將您的設計修改爲與其他不同的設計。

實際上,有一種更容易和普通的方法,需要很少的步驟來實現。

  1. 製作方法IsMatch靜態。
  2. 返回Expression<{your entity here}, bool>直接從IsMatch
  3. 通過它喜歡:({your entity here}.IsMatch({parameters}))

休息能保持一樣的,你現在有。

編輯:例 這將與特定實體的工作,所以我會asume你的實體是訂單。替換你自己的實體。

public static Expression<Func<Order, bool>> IsMatch(int id, ...) // static method, that returns filtering expression 
{ 
    return i => i.Id == id; // create the filtering criteria 
} 

然後調用它像:

count(some_guid, Order.IsMatch(entityId, inviterId, routeId, luggageTypeId)); 
+0

你能舉個例子嗎?我沒有理解你最後的兩個步驟。 – Naor 2011-05-01 12:54:11

+0

您寫的靜態IsMatch方法是否必須返回不基於其他函數的委託?我可以使用例如「return i => i.MyMethod(id);」? – Naor 2011-05-02 03:03:49

+0

不可以。您必須使用eiter完整地創建它作爲表達式或Ladislav所說的,將您的函數映射到存儲過程。 – Euphoric 2011-05-02 06:23:09

相關問題