查詢 是從數據源擷取數據的表達式。 查詢會以專用的查詢語言表示。 經過一段時間后,已針對不同類型的數據源開發不同的語言,例如關係資料庫 SQL 和 XML 的 XQuery。 這可讓應用程式開發人員瞭解支援之每種數據源或數據格式的新查詢語言。
Language-Integrated Query(LINQ)是一種工具,通過提供一致的模型,來簡化在各種數據源和格式上操作數據的情況。 在 LINQ 查詢中,您一律會使用 物件。 您可以使用相同的基本編碼模式來查詢和轉換 XML 檔、SQL 資料庫、ADO.NET 數據集和實體、.NET Framework 集合,以及 LINQ 提供者可供使用的任何其他來源或格式。 本文件說明建立和使用基本 LINQ 查詢的三個階段。
查詢作業的三個階段
LINQ 查詢作業包含三個動作:
取得數據源或來源。
建立查詢。
執行查詢。
在 LINQ 中,查詢的執行與建立查詢不同。 您不只要建立查詢即可擷取任何數據。 本主題稍後會更詳細地討論這一點。
下列範例說明查詢作業的三個部分。 此範例會使用整數陣列作為方便的數據源,以供示範之用。 不過,相同的概念也適用於其他數據源。
備註
在 [專案設計工具 (Visual Basic) 的 [編譯] 頁面] 上,確保 [選項推斷] 設定為 [開啟]。
' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}
' Query creation.
Dim evensQuery = From num In numbers
Where num Mod 2 = 0
Select num
' Query execution.
For Each number In evensQuery
Console.Write(number & " ")
Next
輸出:
0 2 4 6
數據源
因為上一個範例中的資料來源是陣列,所以它會隱含地支援泛型 IEnumerable<T> 介面。 正是這個事實可讓您使用陣列做為LINQ查詢的數據源。 支援 IEnumerable<T> 或衍生介面的類型,例如泛型 IQueryable<T>,稱為 可查詢的類型。
作為隱含可查詢的類型,陣列不需要修改或特殊處理,才能做為LINQ數據源。 任何支援 IEnumerable<T>、包括 .NET Framework 類別庫中泛型 List<T>、 Dictionary<TKey,TValue>和其他類別的集合類型也是如此。
如果源數據尚未實 IEnumerable<T>作 ,則需要 LINQ 提供者來實作該數據源 的標準查詢運算子 功能。 例如,LINQ to XML 會處理將 XML 檔載入可 XElement 查詢類型的工作,如下列範例所示。 如需標準查詢運算符的詳細資訊,請參閱標準查詢運算符概觀(Visual Basic)。
' Create a data source from an XML document.
Dim contacts = XElement.Load("c:\myContactList.xml")
使用 LINQ to SQL 時,您必須先在設計時間手動或使用 Visual Studio 中的 LINQ to SQL Tools 來建立物件關係型對應。 您可以針對物件撰寫查詢,並在運行時間 LINQ to SQL 處理與資料庫的通訊。 在下列範例中, customers 表示資料庫中的特定資料表,並支援 Table<TEntity> 泛型 IQueryable<T>。
' Create a data source from a SQL table.
Dim db As New DataContext("C:\Northwind\Northwnd.mdf")
Dim customers As Table(Of Customer) = db.GetTable(Of Customer)
如需如何建立特定數據源類型的詳細資訊,請參閱各種 LINQ 提供者的檔。 (如需這些提供者的清單,請參閱 LINQ (Language-Integrated 查詢)。 基本規則很簡單:LINQ 數據源是任何支援泛型 IEnumerable<T> 介面的物件,或繼承自它的介面。
備註
支援非泛型ArrayList介面的類型IEnumerable也可以當做LINQ數據源使用。 如需使用 ArrayList的範例,請參閱如何:使用 LINQ 查詢 ArrayList(Visual Basic)。
查詢內容
在查詢中,您可以指定您想要從數據源或來源擷取哪些資訊。 您也可以選擇指定該資訊在傳回之前應如何排序、分組或結構化。 為了啟用查詢建立,Visual Basic 已將新的查詢語法併入語言。
執行時,下列範例中的查詢會從整數陣列 numbers傳回所有偶數。
' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}
' Query creation.
Dim evensQuery = From num In numbers
Where num Mod 2 = 0
Select num
' Query execution.
For Each number In evensQuery
Console.Write(number & " ")
Next
查詢表示式包含三個子句:From、Where和 Select。 基本 查詢作業 (Visual Basic) 會討論每個查詢表達式子句的特定函式和用途。 如需詳細資訊,請參閱 查詢。 請注意,在 LINQ 中,查詢定義通常會儲存在變數中,並在稍後執行。 查詢變數,例如 evensQuery 在上一個範例中,必須是可查詢的類型。 的類型 evensQuery 為 IEnumerable(Of Integer),由編譯程式使用本機類型推斷指派。
請務必記住,查詢變數本身不會採取任何動作,而且不會傳回任何數據。 它只會儲存查詢定義。 在上一個範例中,它是 For Each 執行查詢的迴圈。
查詢執行
查詢執行與查詢建立不同。 查詢建立會定義查詢,但執行是由不同的機制觸發。 只要已定義查詢即可執行(立即執行),或可以儲存定義,且稍後可以執行查詢(延遲執行)。
延遲執行
典型的 LINQ 查詢類似於上一個範例 evensQuery 中定義的查詢。 它會建立查詢,但不會立即執行。 相反地,查詢定義會儲存在查詢變數 evensQuery中。 您稍後會執行查詢,通常是使用 For Each 循環來傳回值序列,或套用標準查詢運算元,例如 Count 或 Max。 此程序稱為 延後執行。
' Query execution that results in a sequence of values.
For Each number In evensQuery
Console.Write(number & " ")
Next
' Query execution that results in a single value.
Dim evens = evensQuery.Count()
針對值序列,您可以使用 迴圈中的 For Each 反覆專案變數來存取擷取的數據(number 在上一個範例中)。 因為查詢變數 evensQuery, 會儲存查詢定義,而不是查詢結果,因此您可以使用查詢變數多次來執行查詢。 例如,您可能會在應用程式中有一個資料庫,而該應用程式會由個別應用程式持續更新。 建立從該資料庫擷取數據的查詢之後,您可以使用 For Each 循環重複執行查詢,每次擷取最新的數據。
下列範例示範延遲執行的運作方式。 在evensQuery2被定義並使用For Each迴圈執行之後,如先前的範例所示,數據源numbers中的某些元素會發生變更。 然後,第二 For Each 個迴圈會再次執行 evensQuery2 。 結果第二次不同,因為 For Each 迴圈會再次使用 中的 numbers新值來執行查詢。
Dim numberArray() = {0, 1, 2, 3, 4, 5, 6}
Dim evensQuery2 = From num In numberArray
Where num Mod 2 = 0
Select num
Console.WriteLine("Evens in original array:")
For Each number In evensQuery2
Console.Write(" " & number)
Next
Console.WriteLine()
' Change a few array elements.
numberArray(1) = 10
numberArray(4) = 22
numberArray(6) = 8
' Run the same query again.
Console.WriteLine(vbCrLf & "Evens in changed array:")
For Each number In evensQuery2
Console.Write(" " & number)
Next
Console.WriteLine()
輸出:
Evens in original array:
0 2 4 6
Evens in changed array:
0 10 2 22 8
立即執行
在延遲執行的查詢中,查詢定義會儲存在查詢變數中,以供日後執行。 在立即執行中,查詢會在其定義時執行。 當您套用需要存取查詢結果個別元素的方法時,就會觸發執行。 直接執行通常是使用其中一個傳回單一值的標準查詢運算符來強制執行。 範例包括 Count、 Max、 Average和 First。 這些標準查詢運算子會在套用查詢后立即執行查詢,以便計算並傳回單一結果。 如需傳回單一值之標準查詢運算子的詳細資訊,請參閱 匯總作業、 元素作業和 數量值作業。
下列查詢會傳回整數陣列中偶數的計數。 查詢定義不會儲存,而且 numEvens 是簡單的 Integer。
Dim numEvens = (From num In numbers
Where num Mod 2 = 0
Select num).Count()
您可以使用Aggregate方法達到相同的結果。
Dim numEvensAgg = Aggregate num In numbers
Where num Mod 2 = 0
Select num
Into Count()
您也可以在查詢(立即)或查詢變數上呼叫 ToList 或 ToArray 方法來強制執行查詢,如下列程式代碼所示。
' Immediate execution.
Dim evensList = (From num In numbers
Where num Mod 2 = 0
Select num).ToList()
' Deferred execution.
Dim evensQuery3 = From num In numbers
Where num Mod 2 = 0
Select num
' . . .
Dim evensArray = evensQuery3.ToArray()
在上述範例中, evensQuery3 是查詢變數,但 evensList 是清單,而且 evensArray 是陣列。
在您想要立即執行查詢並在單一集合物件中快取結果的案例中,使用 ToList 或 ToArray 強制立即執行特別有用。 如需這些方法的詳細資訊,請參閱 轉換數據類型。
您也可以使用 IEnumerable 方法,例如 IEnumerable.GetEnumerator 方法來執行查詢。