標籤:建議 套介面 temp ted context not strong string 需要
建議29:區別LINQ查詢中的IEnumerable<T>和IQueryable<T>
LINQ查詢一共提供了兩類擴充方法,在System.Linq命名空間下,有兩個靜態類:Enumerable類,它針對繼承了IEnumerable<T>介面的集合進行擴充;Queryable類,它針對繼承了IQueryable<T>介面的集合類進行擴紮。介面IQueryable<T>也是繼承了IEnumerable<T>介面的,所以,致使兩個介面的方法在很大程度上時一致的。
LINQ查詢從功能上來講實際上可分為3類:LINQ to OBJECTS、LINQ to SQL、LINQ to XML。設計兩套介面的目的在於區分對待LINQ to OBJECTS、LINQ to SQL,兩者對於查詢的處理在內部使用的是完全不同的機制。針對LINQ to OBJECTS時,使用Enumerable中的擴充方法對本地集合進行排序和查詢等操作,查詢參數接受的是Func<>。Func<>叫做謂語運算式,相當於一個委託。針對LINQ to SQL時,則使用Queryable中的擴充方法,它接受的是Expression<>。Expression<>用於封裝Func<>。LINQ to SQL最終會將運算式樹狀架構轉換成相應的SQL語句,然後在資料庫中執行。
簡單的說:本機資料源用IEnumerable<T>,遠端資料源用IQueryable<T>。
在使用IEnumerable<T>和IQueryable<T>的時候還需要注意,IEnumerable<T>查詢的邏輯可言直接用我們自訂的方法,而IQueryable<T>則不能使用自訂的方法,它必須先產生運算式樹狀架構,查詢由LINQ to SQL引擎處理。在使用IQueryable<T>查詢的時候,若果使用自訂方法,則會拋出異常。
DataContext ctx = new DataContext("server=192.168.0.102;database=Temp;uid=sa;pwd=sa123"); Table<Person> persons = ctx.GetTable<Person>(); var temp1 = from p in persons where OlderThan20(p.Age) select p; foreach (var item in temp1) { Console.WriteLine(string.Format("Name:{0}\tAge:{1}", item.Name, item.Age)); }
拋出異常NotSupportedException:方法“Boolean OlderThan20(Int32)”不支援轉換為SQL。
但是,如果我們將查詢轉換成一個IEnumerable<T>查詢,這種模式是支援的:
List<int> list = new List<int>() { 17, 18, 19, 20, 21, 22, }; var temp2 = from c in list where OlderTan20(c) select c;
轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技
【轉】編寫高品質代碼改善C#程式的157個建議——建議29:區別LINQ查詢中的IEnumerable<T>和IQueryable<T>