查詢是一種從數據源檢索數據的表達式。 隨著時間的推移,人們已經為各種數據源開發了不同的語言;例如,用於關系數據庫的 SQL 和用於 XML 的 XQuery。 因此,開發人員不得不針對他們必須支持的每種數據源或數據格式而學習新的查詢語言。 LINQ 通過提供一種跨數據源和數據格式使用數據的一致模型,簡化了這一情況。在 LINQ 查詢中,始終會用到對象。可以使用相同的編碼模式來查詢和轉換 XML 文檔、SQL 數據庫、ADO.NET 數據集、.NET 集合中的數據以及對其有 LINQ 提供程序可用的任何其他格式的數據。
1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 //1.獲取數據源 6 var nums = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; 7 8 //2.創建查詢 9 var numQuery = 10 from num in nums 11 where (num % 2) == 0 12 select num; 13 14 //3.執行查詢 15 foreach (var num in numQuery) 16 { 17 Console.WriteLine("{0}", num); 18 } 19 } 20 }
下圖顯示了完整的查詢操作。在 LINQ 中,查詢的執行與查詢本身截然不同;換句話說,查詢本身指的是只創建查詢變量,不檢索任何數據。
在上一個示例中,由於數據源是數組,因此它隱式支持泛型 IEnumerable<T> 接口。 支持 IEnumerable<T> 或派生接口(如泛型 IQueryable<T>)的類型稱為可查詢類型。
可查詢類型不需要進行修改或特殊處理就可以用作 LINQ 數據源。如果源數據還沒有作為可查詢類型出現在內存中,則 LINQ 提供程序必須以此方式表示源數據。 例如,LINQ to XML 將 XML 文檔加載到可查詢的 XElement 類型中:1 //從 XML 中創建數據源 2 //using System.Xml.Linq; 3 var contacts = XElement.Load(@"c:\xxx.xml");
在 LINQ to SQL 中,首先需要創建對象關系映射。 針對這些對象編寫查詢,然後由 LINQ to SQL 在運行時處理與數據庫的通信。在下面的示例中,Customers 表示數據庫中的特定表。
1 var db = new Northwnd(@"c:\northwnd.mdf"); 2 3 //查詢在倫敦的客戶 4 var custQuery = 5 from cust in db.Customers 6 where cust.City == "London" 7 select cust;
查詢指定要從數據源中檢索的信息。 查詢還可以指定在返回這些信息之前如何對其進行排序、分組和結構化。 查詢存儲在查詢變量中,並用查詢表達式進行初始化。
之前的示例中的查詢是從整數數組中返回所有的偶數。 該查詢表達式包含三個子句:from、where 和 select。(如果您熟悉 SQL,您會注意到這些子句的順序與 SQL 中的順序相反。)from 子句指定數據源,where 子句指定應用篩選器,select 子句指定返回的元素的類型。 目前需要注意的是,在 LINQ 中,查詢變量本身不執行任何操作並且不返回任何數據。 它只是存儲在以後某個時刻執行查詢時為生成結果而必需的信息。如前所述,查詢變量本身只是存儲查詢命令。 實際的查詢執行會延遲到在 foreach 語句中循環訪問查詢變量時發生。 此概念稱為“延遲執行”。
對一系列源元素執行聚合函數的查詢必須首先循環訪問這些元素。Count、Max、Average 和 First 就屬於此類查詢。由於查詢本身必須使用 foreach 以便返回結果,因此這些查詢在執行時不使用顯式 foreach 語句。另外還要注意,這些類型的查詢返回單個值,而不是 IEnumerable 集合。
var numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var evenNumQuery = from num in numbers where (num % 2) == 0 select num; var evenNumCount = evenNumQuery.Count();
若要強制立即執行任意查詢並緩存其結果,可以調用 ToList<TSource> 或 ToArray<TSource> 方法。
1 var numQuery2 = 2 (from num in numbers 3 where (num % 2) == 0 4 select num).ToList(); 5 6 var numQuery3 = 7 (from num in numbers 8 where (num % 2) == 0 9 select num).ToArray();
此外,還可以通過在緊跟查詢表達式之後的位置放置一個 foreach 循環來強制執行查詢。但是,通過調用 ToList 或 ToArray,也可以將所有數據緩存在單個集合對象中。