Visual Basic 中的 LINQ 簡介

Language-Integrated Query (LINQ) 將查詢功能加入 Visual Basic,在您使用所有類型的資料時,為您提供簡單而強大的功能。 LINQ 將查詢當成 Visual Basic 語言的一部分導入,而不是將查詢傳送至資料庫加以處理,或針對您搜尋的各種類型資料,使用不同的查詢語法。 它使用統一的語法,不論資料類型為何。

LINQ 可讓您從 SQL Server 資料庫、XML、記憶體內部的陣列和集合、ADO.NET 資料集,或任何支援 LINQ 的其他遠端或本機資料來源查詢資料。 使用一般的 Visual Basic 語言元素即可執行上述所有作業。 因為查詢是以 Visual Basic 語言撰寫而成,所以傳回的查詢結果會是強類型物件。 這些物件支援 IntelliSense,讓您加快撰寫程式碼的速度,並在編譯階段即捕捉查詢中的錯誤,而不是在執行階段。 LINQ 查詢可用做其他查詢來源,以精簡結果。 它們也可以繫結至控制項,讓使用者輕鬆地檢視和修改查詢結果。

例如,下列程式碼範例顯示的 LINQ 查詢,會從集合中傳回一份客戶清單,並根據位置分組。

' Obtain a list of customers.
Dim customers As List(Of Customer) = GetCustomers()

' Return customers that are grouped based on country.
Dim countries = From cust In customers
                Order By cust.Country, cust.City
                Group By CountryName = cust.Country
                Into CustomersInCountry = Group, Count()
                Order By CountryName

' Output the results.
For Each country In countries
    Debug.WriteLine(country.CountryName & " count=" & country.Count)

    For Each customer In country.CustomersInCountry
        Debug.WriteLine("   " & customer.CompanyName & "  " & customer.City)
    Next
Next

' Output:
'   Canada count=2
'      Contoso, Ltd  Halifax
'      Fabrikam, Inc.  Vancouver
'   United States count=1
'      Margie's Travel  Redmond

執行範例

執行簡介和 LINQ 查詢結構一節中的範例,包括下列程式碼,會傳回客戶和訂單清單。

' Return a list of customers.
Private Function GetCustomers() As List(Of Customer)
    Return New List(Of Customer) From
        {
            New Customer With {.CustomerID = 1, .CompanyName = "Contoso, Ltd", .City = "Halifax", .Country = "Canada"},
            New Customer With {.CustomerID = 2, .CompanyName = "Margie's Travel", .City = "Redmond", .Country = "United States"},
            New Customer With {.CustomerID = 3, .CompanyName = "Fabrikam, Inc.", .City = "Vancouver", .Country = "Canada"}
        }
End Function

' Return a list of orders.
Private Function GetOrders() As List(Of Order)
    Return New List(Of Order) From
        {
            New Order With {.CustomerID = 1, .Amount = "200.00"},
            New Order With {.CustomerID = 3, .Amount = "600.00"},
            New Order With {.CustomerID = 1, .Amount = "300.00"},
            New Order With {.CustomerID = 2, .Amount = "100.00"},
            New Order With {.CustomerID = 3, .Amount = "800.00"}
        }
End Function

' Customer Class.
Private Class Customer
    Public Property CustomerID As Integer
    Public Property CompanyName As String
    Public Property City As String
    Public Property Country As String
End Class

' Order Class.
Private Class Order
    Public Property CustomerID As Integer
    Public Property Amount As Decimal
End Class

LINQ 提供者

LINQ 提供者會對應 Visual Basic LINQ 查詢和查詢中的資料來源。 當您撰寫 LINQ 查詢時,提供者會接受該查詢,並將它轉譯成資料來源能夠執行的命令。 提供者也會將資料從來源轉換成組成查詢結果的物件。 最後,當您將更新傳送至資料來源時,它會將物件轉換成資料。

Visual Basic 包含下列 LINQ 提供者。

提供者 描述
LINQ to Objects LINQ to Objects 提供者讓您查詢記憶體內部的集合和陣列。 如果物件支援 IEnumerableIEnumerable<T> 介面,LINQ to Objects 提供者就會讓您查詢。

匯入 System.Linq 命名空間就可以啟用 LINQ to Objects 提供者,所有 Visual Basic 專案都預設匯入。

如需 LINQ to Objects 提供者的詳細資訊,請參閱 LINQ to Objects
LINQ to SQL LINQ to SQL 提供者可讓您查詢及修改 SQL Server 資料庫中的資料。 這可讓您輕鬆對應應用程式的物件模型與資料庫的資料表和物件。

Visual Basic 納入物件關聯式設計工具 (O/R 設計工具),讓 LINQ to SQL 更好用。 這個設計工具是用於在對應至資料庫物件的應用程式中建立物件模型。 O/R 設計工具也提供將預存程序和函式對應至 DataContext 物件的功能,該工具會管理與資料庫的通訊,並且儲存開放式並行存取檢查的狀態。

如需 LINQ to SQL 提供者的詳細資訊,請參閱 LINQ to SQL。 如需物件關聯式設計工具的詳細資訊,請參閱 Visual Studio 中的 LINQ to SQL 工具
LINQ to XML LINQ to XML 提供者可讓您查詢及修改 XML。 您可以修改記憶體內部的 XML,也可以從檔案載入 XML 並將 XML 儲存到檔案。

此外,LINQ to XML 提供者也會啟用 XML 常值和 XML 軸屬性,讓您直接在 Visual Basic 程式碼中撰寫 XML。 如需詳細資訊,請參閱 XML
LINQ to DataSet LINQ to DataSet 提供者可讓您查詢及更新 ADO.NET 資料集中的資料。 您可以將 LINQ 的強大功能加入使用資料集的應用程式,以簡化並擴充查詢、彙總及更新資料集資料的能力。

如需詳細資訊,請參閱 LINQ to DataSet

LINQ 查詢的結構

LINQ 查詢,通常稱為「查詢運算式」,由識別查詢的資料來源和反覆運算變數的查詢子句組合而成。 查詢運算式也可以包含排序、篩選、群組和聯結的指示,或套用至來源資料的計算。 查詢運算式語法類似於 SQL 語法,所以您會覺得大部分的語法很熟悉。

查詢運算式以 From 子句開頭。 這個子句會識別查詢和變數的來源資料,這些變數用於分別參考來源資料的每個項目。 這些變數稱為「範圍變數」或「反覆運算變數」。 查詢一定要有 From 子句,Aggregate 查詢除外,因為 From 子句對這類查詢為選擇性項目。 識別出 FromAggregate 子句中的查詢範圍和來源之後,您可以包含任何查詢子句組合以精簡查詢。 如需查詢子句的詳細資訊,請參閱本主題後文中的 Visual Basic LINQ 查詢運算子。 例如,下列查詢會將客戶資料的來源集合識別為 customers 變數,而反覆運算變數則稱之為 cust

Dim customers = GetCustomers()

Dim queryResults = From cust In customers

For Each result In queryResults
    Debug.WriteLine(result.CompanyName & "  " & result.Country)
Next

' Output:
'   Contoso, Ltd  Canada
'   Margie's Travel  United States
'   Fabrikam, Inc.  Canada

這個範例本身就是個有效的查詢;但是當您加入更多的查詢子句來精簡結果時,查詢就會變得更強大。 例如,您可以加入 Where 子句,根據一或多個值來篩選結果。 查詢運算式是單行程式碼,您只可以將其他查詢子句附加至查詢結尾。 您可以使用底線 (_) 行接續字元,將查詢分割成多行文字,以提高可讀性。 下列程式碼範例顯示的查詢範例,包含 Where 子句。

Dim queryResults = From cust In customers
                   Where cust.Country = "Canada"

另一個功能強大的查詢子句是 Select 子句,可讓您只傳回從資料來源選取的欄位。 LINQ 查詢會傳回可列舉的強類型物件集合。 查詢可以傳回匿名類型或具名類型的集合。 您可以使用 Select 子句,只傳回資料來源的單一欄位。 當您這麼做時,傳回的集合類型就是該單一欄位的類型。 您也可以使用 Select 子句,傳回資料來源的多個欄位。 當您這麼做時,傳回的集合類型就是新的匿名類型。 您也可以比對查詢傳回的欄位和指定的具名類型欄位。 下列程式碼範例顯示傳回匿名類型集合的查詢運算式,該類型具有填入來自資料來源之選取欄位資料的成員。

Dim queryResults = From cust In customers
               Where cust.Country = "Canada"
               Select cust.CompanyName, cust.Country

LINQ 查詢也可以用來結合多個資料來源,並傳回單一結果。 使用一或多個 From 子句,或使用 JoinGroup Join 查詢子句,即可完成。 下列程式碼範例顯示的查詢運算式,結合了客戶和訂單資料,並傳回包含客戶和訂單資料的匿名類型集合。

Dim customers = GetCustomers()
Dim orders = GetOrders()

Dim queryResults = From cust In customers, ord In orders
           Where cust.CustomerID = ord.CustomerID
           Select cust, ord

For Each result In queryResults
    Debug.WriteLine(result.ord.Amount & "  " & result.ord.CustomerID & "  " & result.cust.CompanyName)
Next

' Output:
'   200.00  1  Contoso, Ltd
'   300.00  1  Contoso, Ltd
'   100.00  2  Margie's Travel
'   600.00  3  Fabrikam, Inc.
'   800.00  3  Fabrikam, Inc.

您可以使用 Group Join 子句建立階層式的查詢結果,其包含客戶物件的集合。 每個客戶物件都有一個屬性,包含該客戶所有訂單的集合。 下列程式碼範例顯示的查詢運算式,結合了階層式結果的客戶和訂單資料,並傳回匿名類型的集合。 查詢傳回的類型包含 CustomerOrders 屬性,內含客戶訂單資料的集合。 它也包含 OrderTotal 屬性,內含該客戶所有訂單小計的總和。 (這個查詢相當於 LEFT OUTER JOIN)。

Dim customers = GetCustomers()
Dim orders = GetOrders()

Dim queryResults = From cust In customers
                   Group Join ord In orders On
                     cust.CustomerID Equals ord.CustomerID
                     Into CustomerOrders = Group,
                          OrderTotal = Sum(ord.Amount)
                   Select cust.CompanyName, cust.CustomerID,
                          CustomerOrders, OrderTotal

For Each result In queryResults
    Debug.WriteLine(result.OrderTotal & "  " & result.CustomerID & "  " & result.CompanyName)
    For Each ordResult In result.CustomerOrders
        Debug.WriteLine("   " & ordResult.Amount)
    Next
Next

' Output:
'   500.00  1  Contoso, Ltd
'      200.00
'      300.00
'   100.00  2  Margie's Travel
'      100.00
'   1400.00  3  Fabrikam, Inc.
'      600.00
'      800.00

另有幾個 LINQ 查詢運算子,可讓您建立功能強大的查詢運算式。 本主題的下一節,將討論查詢運算式中可包含的各種查詢子句。 如需 Visual Basic 查詢子句的詳細資訊,請參閱查詢

Visual Basic LINQ 查詢運算子

System.Linq 命名空間和其他支援 LINQ 查詢的命名空間中的類別,包含了依應用程式需求建立並精簡查詢的呼叫方法。 Visual Basic 包含下列常見查詢子句的關鍵字。 如需 Visual Basic 查詢子句的詳細資訊,請參閱查詢

From 子句

查詢必須有 From 子句Aggregate 子句才能開始。 From 子句會指定查詢的來源集合和反覆運算變數。 例如:

' Returns the company name for all customers for which
' the Country is equal to "Canada".
Dim names = From cust In customers
            Where cust.Country = "Canada"
            Select cust.CompanyName

Select 子句

選擇性。 Select 子句宣告一組查詢的反覆運算變數。 例如:

' Returns the company name and ID value for each
' customer as a collection of a new anonymous type.
Dim customerList = From cust In customers
                   Select cust.CompanyName, cust.CustomerID

如果不指定 Select 子句,則查詢的反覆運算變數即由 FromAggregate 子句指定的反覆運算變數組成。

Where 子句

選擇性。 Where 子句指定查詢的篩選條件。 例如:

' Returns all product names for which the Category of
' the product is "Beverages".
Dim names = From product In products
            Where product.Category = "Beverages"
            Select product.Name

Order By 子句

選擇性。 Order By 子句指定查詢中資料行的排序次序。 例如:

' Returns a list of books sorted by price in 
' ascending order.
Dim titlesAscendingPrice = From b In books
                           Order By b.price

Join 子句

選擇性。 Join 子句將兩個集合合併成單一集合。 例如:

' Returns a combined collection of all of the 
' processes currently running and a descriptive
' name for the process taken from a list of 
' descriptive names.
Dim processes = From proc In Process.GetProcesses
                Join desc In processDescriptions
                  On proc.ProcessName Equals desc.ProcessName
                Select proc.ProcessName, proc.Id, desc.Description

Group By 子句

選擇性。 Group By 子句將查詢結果的元素分組。 該子句可用來將彙總函式套用至每個群組。 例如:

' Returns a list of orders grouped by the order date
' and sorted in ascending order by the order date.
Dim orderList = From order In orders
                Order By order.OrderDate
                Group By OrderDate = order.OrderDate
                Into OrdersByDate = Group

Group Join 子句

選擇性。 Group Join 子句將兩個集合合併成單一階層式集合。 例如:

' Returns a combined collection of customers and
' customer orders.
Dim customerList = From cust In customers
                   Group Join ord In orders On
                     cust.CustomerID Equals ord.CustomerID
                   Into CustomerOrders = Group,
                        TotalOfOrders = Sum(ord.Amount)
                   Select cust.CompanyName, cust.CustomerID,
                          CustomerOrders, TotalOfOrders

Aggregate 子句

查詢必須有 Aggregate 子句From 子句才能開始。 Aggregate 子句會將一或多個彙總函式套用至集合。 例如,您可以使用 Aggregate 子句來計算查詢所傳回的所有元素總和,如下列範例所示。

' Returns the sum of all order amounts.
Dim orderTotal = Aggregate order In orders
                 Into Sum(order.Amount)

也可以使用 Aggregate 子句修改查詢。 例如,您可以使用 Aggregate 子句執行相關查詢集合的計算。 例如:

' Returns the customer company name and largest 
' order amount for each customer.
Dim customerMax = From cust In customers
                  Aggregate order In cust.Orders
                  Into MaxOrder = Max(order.Amount)
                  Select cust.CompanyName, MaxOrder

Let 子句

選擇性。 Let 子句計算值,並將其指派給查詢中的新變數。 例如:

' Returns a list of products with a calculation of
' a ten percent discount.
Dim discountedProducts = From prod In products
                         Let Discount = prod.UnitPrice * 0.1
                         Where Discount >= 50
                         Select prod.Name, prod.UnitPrice, Discount

Distinct 子句

選擇性。 Distinct 子句限制目前反覆運算變數的值,以消除查詢結果中重複的值。 例如:

' Returns a list of cities with no duplicate entries.
Dim cities = From item In customers
             Select item.City
             Distinct

Skip 子句

選擇性。 Skip 子句略過集合中指定數目的元素,然後傳回其餘元素。 例如:

' Returns a list of customers. The first 10 customers
' are ignored and the remaining customers are
' returned.
Dim customerList = From cust In customers
                   Skip 10

Skip While 子句

選擇性。 只要指定的條件為 trueSkip While 子句便會略過集合中的元素,然後傳回其餘元素。 例如:

' Returns a list of customers. The query ignores all
' customers until the first customer for whom
' IsSubscriber returns false. That customer and all
' remaining customers are returned.
Dim customerList = From cust In customers
                   Skip While IsSubscriber(cust)

Take 子句

選擇性。 Take 子句從集合開頭傳回指定數目的連續元素。 例如:

' Returns the first 10 customers.
Dim customerList = From cust In customers
                   Take 10

Take While 子句

選擇性。 只要指定的條件為 trueTake While 子句便會包含集合中的元素,並略過其餘元素。 例如:

' Returns a list of customers. The query returns
' customers until the first customer for whom 
' HasOrders returns false. That customer and all 
' remaining customers are ignored.
Dim customersWithOrders = From cust In customers
                          Order By cust.Orders.Count Descending
                          Take While HasOrders(cust)

使用其他 LINQ 查詢功能

透過呼叫 LINQ 提供的可列舉和可查詢類型的成員,您可以使用其他的 LINQ 查詢功能。 透過呼叫查詢運算式結果上的特定查詢運算子,您可以使用這些額外的功能。 例如,下列程式碼範例使用 Enumerable.Union 方法,將兩個查詢結果合併成一個查詢結果。 它使用 Enumerable.ToList 方法傳回泛型清單的查詢結果。

Public Function GetAllCustomers() As List(Of Customer)
    Dim customers1 = From cust In domesticCustomers
    Dim customers2 = From cust In internationalCustomers

    Dim customerList = customers1.Union(customers2)

    Return customerList.ToList()
End Function

如需其他 LINQ 功能的詳細資訊,請參閱標準查詢運算子概觀

使用 LINQ to SQL 連接到資料庫

在 Visual Basic 中,您使用 LINQ to SQL 檔案識別要存取的 SQL Server 資料庫物件,例如資料表、檢視和預存程序。 LINQ to SQL 檔案的副檔名為 .dbml。

當您有 SQL Server 資料庫的有效連接時,可以將 [LINQ to SQL 類別] 項目範本加入專案。 這會顯示物件關聯式設計工具 (O/R 設計工具)。 O/R 設計工具可讓您將想要存取的程式碼項目,從 [伺服器總管]/[資料庫總管] 拖曳至設計工具介面上。 LINQ to SQL 檔案將 DataContext 物件加入專案。 此物件包含您想要存取的資料表和檢視的屬性和集合,以及您想要呼叫的預存程序方法。 將變更儲存至 LINQ to SQL (.dbml) 檔案之後,參考 O/R 設計工具所定義的 DataContext 物件,您就可以存取程式碼中的這些物件。 專案的 DataContext 物件依據您的 LINQ to SQL 檔案名稱來命名。 例如,名為 Northwind.dbml 的 LINQ to SQL 檔案,會建立名為 NorthwindDataContextDataContext 物件。

如需逐步指示的範例,請參閱如何:查詢資料庫如何:呼叫預存程序

支援 LINQ 的 Visual Basic 功能

Visual Basic 包含其他值得注意的功能,讓 LINQ 簡單易用,並減少為執行 LINQ 查詢所必須撰寫的程式碼數量。 其中包括下列各項:

  • 匿名類型:可讓您根據查詢結果建立新的類型。

  • 隱含類型變數:可讓您延後指定類型,並讓編譯器根據查詢結果推斷類型。

  • 擴充方法:可讓您以自己的方法擴充現有的類型,卻不修改類型本身。

如需詳細資訊,請參閱支援 LINQ 的 Visual Basic 功能

延期與立即執行查詢

查詢執行會與建立查詢分開。 查詢建立之後,會另有機制觸發執行。 查詢一經定義便可執行 (「立即執行」),或者儲存定義以待稍後執行查詢 (「延後執行」)。

當您建立查詢時,查詢本身預設不會立即執行。 反而會將查詢定義儲存在變數中,用以參考查詢結果。 稍後存取程式碼中的查詢結果變數時,例如在 For…Next 迴圈中,就會執行查詢。 此程序稱為「延後執行」

查詢也可以在定義當時執行,這稱為「立即執行」。 套用要求存取查詢結果個別項目的方法,可觸發立即執行。 這個結果可能會包括彙總函式,例如 CountSumAverageMinMax。 如需彙總函式的詳細資訊,請參閱 Aggregate 子句

使用 ToListToArray 方法也會強制立即執行。 當您想要立即執行查詢並快取結果時,這方法非常好用。 如需這些方法的詳細資訊,請參閱轉換資料類型

如需查詢執行的詳細資訊,請參閱撰寫第一個 LINQ 查詢

Visual Basic 中的 XML

Visual Basic 中的 XML 功能包括 XML 常值和 XML 軸屬性,讓您輕鬆建立、存取、查詢及修改程式碼中的 XML。 XML 常值可讓您直接在程式碼中撰寫 XML。 Visual Basic 編譯器將 XML 視為第一級的資料物件。

下列程式碼範例示範如何建立 XML 項目、存取其子項目和屬性,以及使用 LINQ 查詢項目內容。

' Place Imports statements at the top of your program.
Imports <xmlns:ns="http://SomeNamespace">

Module Sample1

    Sub SampleTransform()

        ' Create test by using a global XML namespace prefix.

        Dim contact =
            <ns:contact>
                <ns:name>Patrick Hines</ns:name>
                <ns:phone ns:type="home">206-555-0144</ns:phone>
                <ns:phone ns:type="work">425-555-0145</ns:phone>
            </ns:contact>

        Dim phoneTypes =
          <phoneTypes>
              <%= From phone In contact.<ns:phone>
                  Select <type><%= phone.@ns:type %></type>
              %>
          </phoneTypes>

        Console.WriteLine(phoneTypes)
    End Sub

End Module

如需詳細資訊,請參閱 XML

主題 說明
XML 說明 Visual Basic 中可查詢的 XML 功能,它們還可讓您在 Visual Basic 程式碼中將 XML 當做第一級資料物件納入。
查詢 提供 Visual Basic 中的查詢子句參考資訊。
LINQ (Language-Integrated Query) 包含 LINQ 的一般資訊、程式設計指南和範例。
LINQ to SQL 包含 LINQ to SQL 的一般資訊、程式設計指南和範例。
LINQ to Objects 包含 LINQ to Objects 的一般資訊、程式設計指南和範例。
LINQ to ADO.NET (入口網站頁面) 包含 LINQ to ADO.NET 的一般資訊、程式設計指南和範例連結。
LINQ to XML 包含 LINQ to XML 的一般資訊、程式設計指南和範例。

如何和逐步解說主題

如何:查詢資料庫

如何:呼叫預存程序

如何:修改資料庫中的資料

如何:使用 Joins 合併資料

如何:排序查詢結果

如何:篩選查詢結果

如何:統計、加總或平均資料

如何:尋找查詢結果中的最小或最大值

如何:指派用來執行更新、插入和刪除的預存程序 (O/R 設計工具)

程式設計 Visual Basic 2008 中的第 17 章:LINQ

另請參閱