撰寫第一個 LINQ 查詢 (Visual Basic)Writing Your First LINQ Query (Visual Basic)

「查詢」** 是指從資料來源中擷取資料的運算式。A query is an expression that retrieves data from a data source. 查詢是以專用的查詢語言表示。Queries are expressed in a dedicated query language. 經過一段時間後,針對不同類型的資料來源(例如,適用于關係資料庫的 SQL 和 XQuery for XML)開發了不同的語言。Over time, different languages have been developed for different types of data sources, for example, SQL for relational databases and XQuery for XML. 如此一來,應用程式開發人員就必須針對支援的每種資料來源或資料格式,學習新的查詢語言。This makes it necessary for the application developer to learn a new query language for each type of data source or data format that is supported.

語言整合式查詢(LINQ)藉由提供一致的模型來處理各種資料來源和格式的資料,從而簡化了這種情況。Language-Integrated Query (LINQ) simplifies the situation by offering a consistent model for working with data across various kinds of data sources and formats. 在 LINQ 查詢中,您一律會使用物件。In a LINQ query, you are always working with objects. 您可以使用相同的基本編碼模式來查詢和轉換 XML 檔、SQL 資料庫、ADO.NET 資料集和實體、.NET Framework 集合,以及可使用 LINQ 提供者的任何其他來源或格式的資料。You use the same basic coding patterns to query and transform data in XML documents, SQL databases, ADO.NET datasets and entities, .NET Framework collections, and any other source or format for which a LINQ provider is available. 本檔說明建立和使用基本 LINQ 查詢的三個階段。This document describes the three phases of the creation and use of basic LINQ queries.

查詢作業的三個階段Three Stages of a Query Operation

LINQ 查詢作業包含三個動作:LINQ query operations consist of three actions:

  1. 取得資料來源或來源。Obtain the data source or sources.

  2. 建立查詢。Create the query.

  3. 執行查詢。Execute the query.

在 LINQ 中,查詢的執行與查詢的建立方式不同。In LINQ, the execution of a query is distinct from the creation of the query. 您只要建立查詢,就不會抓取任何資料。You do not retrieve any data just by creating a query. 本主題稍後會詳細討論這一點。This point is discussed in more detail later in this topic.

下列範例說明查詢作業的三個部分。The following example illustrates the three parts of a query operation. 此範例會使用整數陣列做為示範用途的方便資料來源。The example uses an array of integers as a convenient data source for demonstration purposes. 不過,相同的概念也適用于其他資料來源。However, the same concepts also apply to other data sources.

注意

[編譯] 頁面上,[專案設計工具] (Visual Basic),確定 [選項推斷] 已設定為 [開啟]。On the Compile Page, Project Designer (Visual Basic), ensure that Option infer is set to On.

' 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

輸出:Output:

0 2 4 6

資料來源The Data Source

因為上一個範例中的資料來源是陣列,所以它會隱含支援泛型 IEnumerable<T> 介面。Because the data source in the previous example is an array, it implicitly supports the generic IEnumerable<T> interface. 這是可讓您使用陣列做為 LINQ 查詢資料來源的事實。It is this fact that enables you to use an array as a data source for a LINQ query. 支援 IEnumerable<T> 或衍生介面的類型,例如泛型 IQueryable<T> 稱為可查詢的類型Types that support IEnumerable<T> or a derived interface such as the generic IQueryable<T> are called queryable types.

以隱含方式查詢的類型而言,陣列不需要進行修改或特殊處理,就能做為 LINQ 資料來源。As an implicitly queryable type, the array requires no modification or special treatment to serve as a LINQ data source. 任何支援的集合類型也是如此 IEnumerable<T> ,包括泛型 List<T>Dictionary<TKey,TValue> 和 .NET Framework Class Library 中的其他類別。The same is true for any collection type that supports IEnumerable<T>, including the generic List<T>, Dictionary<TKey,TValue>, and other classes in the .NET Framework class library.

如果來源資料尚未執行 IEnumerable<T> ,則需要 LINQ 提供者,才能為該資料來源執行標準查詢運算子的功能。If the source data does not already implement IEnumerable<T>, a LINQ provider is needed to implement the functionality of the standard query operators for that data source. 例如,會 LINQ to XMLLINQ to XML 處理將 XML 檔載入到可查詢型別的工作 XElement ,如下列範例所示。For example, LINQ to XMLLINQ to XML handles the work of loading an XML document into a queryable XElement type, as shown in the following example. 如需標準查詢運算子的詳細資訊,請參閱標準查詢運算子總覽(Visual Basic)For more information about standard query operators, see Standard Query Operators Overview (Visual Basic).

' Create a data source from an XML document.
Dim contacts = XElement.Load("c:\myContactList.xml")

LINQ to SQLLINQ to SQL 中,您會先以手動方式或使用 Visual Studio中 Visual Studio 中的 LINQ to SQL 工具,在設計階段建立物件關聯式對應。With LINQ to SQLLINQ to SQL, you first create an object-relational mapping at design time, either manually or by using the LINQ to SQL Tools in Visual Studio in Visual Studio. 您可以針對物件撰寫查詢,而 LINQ to SQLLINQ to SQL 則會在執行階段處理與資料庫之間的通訊。You write your queries against the objects, and at run-time LINQ to SQLLINQ to SQL handles the communication with the database. 在下列範例中, customers 代表資料庫中的特定資料表,並 Table<TEntity> 支援泛型 IQueryable<T>In the following example, customers represents a specific table in the database, and Table<TEntity> supports generic 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 提供者的檔。For more information about how to create specific types of data sources, see the documentation for the various LINQ providers. (如需這些提供者的清單,請參閱LINQ (語言整合式查詢))。基本規則很簡單: LINQ 資料來源是支援泛型介面的任何物件 IEnumerable<T> ,或繼承自它的介面。(For a list of these providers, see LINQ (Language-Integrated Query).) The basic rule is simple: a LINQ data source is any object that supports the generic IEnumerable<T> interface, or an interface that inherits from it.

注意

ArrayList支援非泛型介面的類型(例如) IEnumerable 也可以當做 LINQ 資料來源使用。Types such as ArrayList that support the non-generic IEnumerable interface can also be used as LINQ data sources. 如需使用的範例 ArrayList ,請參閱如何:使用 LINQ 查詢 ArrayList (Visual Basic)For an example that uses an ArrayList, see How to: Query an ArrayList with LINQ (Visual Basic).

查詢The Query

在查詢中,您可以指定您想要從資料來源或來源中取出的資訊。In the query, you specify what information you want to retrieve from the data source or sources. 您也可以選擇指定該資訊在傳回之前應如何排序、分組或結構化。You also have the option of specifying how that information should be sorted, grouped, or structured before it is returned. 若要啟用查詢建立,Visual Basic 已將新的查詢語法併入語言中。To enable query creation, Visual Basic has incorporated new query syntax into the language.

執行時,下列範例中的查詢會傳回整數陣列中的所有偶數數位 numbersWhen it is executed, the query in the following example returns all the even numbers from an integer array, 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

查詢運算式包含三個子句: FromWhereSelectThe query expression contains three clauses: From, Where, and Select. 基本查詢作業(Visual Basic)中會討論每個查詢運算式子句的特定函數和用途。The specific function and purpose of each query expression clause is discussed in Basic Query Operations (Visual Basic). 如需詳細資訊,請參閱查詢For more information, see Queries. 請注意,在 LINQ 中,查詢定義通常會儲存在變數中,並于稍後執行。Note that in LINQ, a query definition often is stored in a variable and executed later. 查詢變數(如 evensQuery 前一個範例中的)必須是可查詢的型別。The query variable, such as evensQuery in the previous example, must be a queryable type. 的類型 evensQueryIEnumerable(Of Integer) ,由編譯器使用區欄位型別推斷來指派。The type of evensQuery is IEnumerable(Of Integer), assigned by the compiler using local type inference.

請務必記住,查詢變數本身不會採取任何動作,也不會傳回任何資料。It is important to remember that the query variable itself takes no action and returns no data. 它只會儲存查詢定義。It only stores the query definition. 在上述範例中,它是 For Each 執行查詢的迴圈。In the previous example, it is the For Each loop that executes the query.

查詢執行Query Execution

查詢執行與查詢建立分開。Query execution is separate from query creation. 查詢建立會定義查詢,但執行是由不同的機制所觸發。Query creation defines the query, but execution is triggered by a different mechanism. 查詢可以在定義(立即執行)時立即執行,或可以儲存定義,而且稍後可以執行查詢(延後執行)。A query can be executed as soon as it is defined (immediate execution), or the definition can be stored and the query can be executed later (deferred execution).

延後執行Deferred Execution

一般的 LINQ 查詢與先前範例中的類似,其中 evensQuery 定義了。A typical LINQ query resembles the one in the previous example, in which evensQuery is defined. 它會建立查詢,但不會立即執行。It creates the query but does not execute it immediately. 相反地,查詢定義會儲存在查詢變數中 evensQueryInstead, the query definition is stored in the query variable evensQuery. 您稍後會執行查詢,通常是透過使用 For Each 迴圈來傳回值的序列,或套用標準查詢運算子(例如 Count 或) MaxYou execute the query later, typically by using a For Each loop, which returns a sequence of values, or by applying a standard query operator, such as Count or Max. 此程式稱為延後執行This process is referred to as deferred execution.

' 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 Eachnumber 在上一個範例中)來存取抓取的資料。For a sequence of values, you access the retrieved data by using the iteration variable in the For Each loop (number in the previous example). 因為查詢變數 evensQuery 會保存查詢定義,而不是查詢結果,所以您可以使用查詢變數多次來執行查詢,而不需要一次。Because the query variable, evensQuery, holds the query definition rather than the query results, you can execute a query as often as you want by using the query variable more than one time. 例如,您的應用程式中可能會有另一個應用程式持續更新的資料庫。For example, you might have a database in your application that is being updated continually by a separate application. 建立可從該資料庫抓取資料的查詢之後,您可以使用 For Each 迴圈來重複執行查詢,每次都會抓取最新的資料。After you have created a query that retrieves data from that database, you can use a For Each loop to execute the query repeatedly, retrieving the most recent data every time.

下列範例示範順延強制的運作方式。The following example demonstrates how deferred execution works. evensQuery2 定義並以迴圈執行之後 For Each (如先前的範例所示),資料來源中的某些元素 numbers 會變更。After evensQuery2 is defined and executed with a For Each loop, as in the previous examples, some elements in the data source numbers are changed. 然後再次執行第二個 For Each 迴圈 evensQuery2Then a second For Each loop runs evensQuery2 again. 第二次的結果會不同,因為 For Each 迴圈會使用中的新值,再次執行查詢 numbersThe results are different the second time, because the For Each loop executes the query again, using the new values in 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()

輸出:Output:

Evens in original array:

0 2 4 6

Evens in changed array:

0 10 2 22 8

立即執行Immediate Execution

在延後執行查詢時,查詢定義會儲存在查詢變數中,以供稍後執行。In deferred execution of queries, the query definition is stored in a query variable for later execution. 在立即執行中,查詢會在其定義時執行。In immediate execution, the query is executed at the time of its definition. 當您套用需要存取查詢結果之個別元素的方法時,就會觸發執行。Execution is triggered when you apply a method that requires access to individual elements of the query result. 通常會使用傳回單一值的其中一個標準查詢運算子來強制立即執行。Immediate execution often is forced by using one of the standard query operators that return single values. 範例包括 CountMaxAverageFirstExamples are Count, Max, Average, and First. 這些標準查詢運算子會在套用查詢時立即執行,以便計算並傳回單一結果。These standard query operators execute the query as soon as they are applied in order to calculate and return a singleton result. 如需傳回單一值之標準查詢運算子的詳細資訊,請參閱匯總作業元素作業數量詞作業For more information about standard query operators that return single values, see Aggregation Operations, Element Operations, and Quantifier Operations.

下列查詢會傳回整數陣列中偶數數目的計數。The following query returns a count of the even numbers in an array of integers. 不會儲存查詢定義,而 numEvens 是簡單的 IntegerThe query definition is not saved, and numEvens is a simple Integer.

Dim numEvens = (From num In numbers
                Where num Mod 2 = 0
                Select num).Count()

您可以使用方法來達到相同的結果 AggregateYou can achieve the same result by using the Aggregate method.

Dim numEvensAgg = Aggregate num In numbers
                  Where num Mod 2 = 0
                  Select num
                  Into Count()

您也可以 ToList ToArray 在查詢(立即)或查詢變數(延後)上呼叫或方法,以強制執行查詢,如下列程式碼所示。You can also force execution of a query by calling the ToList or ToArray method on a query (immediate) or query variable (deferred), as shown in the following code.

' 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 是陣列。In the previous examples, evensQuery3 is a query variable, but evensList is a list and evensArray is an array.

ToList ToArray 當您想要立即執行查詢,並快取單一集合物件中的結果時,使用或來強制立即執行會特別有用。Using ToList or ToArray to force immediate execution is especially useful in scenarios in which you want to execute the query immediately and cache the results in a single collection object. 如需這些方法的詳細資訊,請參閱轉換資料類型For more information about these methods, see Converting Data Types.

您也可以使用方法(例如方法)來執行查詢 IEnumerable IEnumerable.GetEnumeratorYou can also cause a query to be executed by using an IEnumerable method such as the IEnumerable.GetEnumerator method.

另請參閱See also