在LINQ to SQL或者LINQ to Object的時候都是相安無事的。
但在Entity Framework上,情況就有不同。
先看Extension methods :
public static class ExtensionMethods { public static int ToInt(this String str) { return Convert.ToInt32(str); } } protected void Page_Load(object sender, EventArgs e) { using (AdventureWorksEntities awe = new AdventureWorksEntities()) { string s = "1"; var select = from p in awe.ProductModel where p.ProductModelID == s.ToInt() select p; Response.Write(select.Count()); } }很無奈,你會得到錯誤訊息:
中文:
LINQ to Entities 無法辨識方法 'Int32 ToInt(System.String)' 方法,而且這個方法無法轉譯成存放區運算式。
英文:
System.NotSupportedException: LINQ to Entities does not recognize the method 'Int32 ToInt(System.String)' method, and this method cannot be translated into a store expression.
可能你會說,不用Extension Methods就可以了,但原來ToString()和Convert.ToString()都會出現類似錯誤。
再看看:
protected void Page_Load(object sender, EventArgs e) { using (AdventureWorksEntities awe = new AdventureWorksEntities()) { object obj = "abcd"; var select = from p in awe.ProductModel where p.CatalogDescription.Contains(obj.ToString()) select p; Response.Write(select.Count()); //錯誤訊息:LINQ to Entities 無法辨識方法 'System.String ToString()' 方法, //而且這個方法無法轉譯成存放區運算式。 } } protected void Page_Load(object sender, EventArgs e) { using (AdventureWorksEntities awe = new AdventureWorksEntities()) { object obj = "abcd"; var select = from p in awe.ProductModel where p.CatalogDescription.Contains(Convert.ToString(obj)) select p; Response.Write(select.Count()); //錯誤訊息:LINQ to Entities 無法辨識方法 'System.String ToString(System.Object)' 方法, //而且這個方法無法轉譯成存放區運算式。 } }
那原因是什麼呢?
根據這裡,這裡和這裡所講。
L2S和EF其中一個最大分別就是,EF把LINQ expressions區分為Client的CLR Method和Server的Canonical Function。
因為EF轉換expressions成SQL時,就必須參照兩者進行轉換。
可以參考MSDN上的CLR Method to Canonical Function Mapping
而大家所見列表中並沒有ToString()和Convert.ToString(),更莫說自定義的Extension Methods,所以才會出現錯誤 : System.NotSupportedException: LINQ to Entities does not recognize the method.
Linq2Sql 一樣做 Expression compile & conversion, 係個 EF support 嘅 function list 唔同唓
回覆刪除