如何:使用 Joins 以 LINQ 合併資料 (Visual Basic)

Visual Basic 提供 JoinGroup Join 查詢子句,可讓您根據集合之間的通用值來合併多個集合的內容。 這些值稱為「索引鍵」值。 熟悉關聯式資料庫概念的開發人員會將 Join 子句視為「內部聯結」,並將 Group Join 子句視為實際上是「左方外部聯結」。

本主題中的範例示範使用 JoinGroup Join 查詢子句來合併資料的幾個方式。

建立專案並新增範例資料

建立包含範例資料和類型的專案

  1. 若要執行本主題中的範例,請開啟 Visual Studio 並新增 Visual Basic 主控台應用程式專案。 按兩下 Visual Basic 所建立的 Module1.vb 檔案。

  2. 本主題中的範例會使用下列程式碼範例中的 PersonPet 類型和資料。 將此程式碼複製到 Visual Basic 所建立的預設 Module1 模組。

    Private _people As List(Of Person)
    Private _pets As List(Of Pet)
    
    Function GetPeople() As List(Of Person)
        If _people Is Nothing Then CreateLists()
        Return _people
    End Function
    
    Function GetPets(ByVal people As List(Of Person)) As List(Of Pet)
        If _pets Is Nothing Then CreateLists()
        Return _pets
    End Function
    
    Private Sub CreateLists()
        Dim pers As Person
    
        _people = New List(Of Person)
        _pets = New List(Of Pet)
    
        pers = New Person With {.FirstName = "Magnus", .LastName = "Hedlund"}
        _people.Add(pers)
        _pets.Add(New Pet With {.Name = "Daisy", .Owner = pers})
    
        pers = New Person With {.FirstName = "Terry", .LastName = "Adams"}
        _people.Add(pers)
        _pets.Add(New Pet With {.Name = "Barley", .Owner = pers})
        _pets.Add(New Pet With {.Name = "Boots", .Owner = pers})
        _pets.Add(New Pet With {.Name = "Blue Moon", .Owner = pers})
    
        pers = New Person With {.FirstName = "Charlotte", .LastName = "Weiss"}
        _people.Add(pers)
        _pets.Add(New Pet With {.Name = "Whiskers", .Owner = pers})
    
        ' Add a person with no pets for the sake of Join examples.
        _people.Add(New Person With {.FirstName = "Arlene", .LastName = "Huff"})
    
        pers = New Person With {.FirstName = "Don", .LastName = "Hall"}
        ' Do not add person to people list for the sake of Join examples.
        _pets.Add(New Pet With {.Name = "Spot", .Owner = pers})
    
        ' Add a pet with no owner for the sake of Join examples.
        _pets.Add(New Pet With {.Name = "Unknown",
                                .Owner = New Person With {.FirstName = String.Empty,
                                                          .LastName = String.Empty}})
    End Sub
    
    Class Person
        Public Property FirstName As String
        Public Property LastName As String
    End Class
    
    Class Pet
        Public Property Name As String
        Public Property Owner As Person
    End Class
    

使用 Join 子句執行內部聯結

「內部聯結」會合併兩個集合的資料。 其會包含與指定索引鍵值相符的項目。 如果任一集合中有任何項目在另一個集合中沒有相符項目,則排除這些項目。

在 Visual Basic 中,LINQ 提供兩個執行「內部聯結」的選項:隱含聯結和明確聯結。

隱含聯結會指定要在 From 子句中聯結的集合,並識別 Where 子句中的相符索引鍵欄位。 Visual Basic 會根據指定的索引鍵欄位隱含聯結這兩個集合。

當您想要明確指出要在聯結中使用的索引鍵欄位時,可以使用 Join 子句來指定明確聯結。 在此情況下,仍可使用 Where 子句來篩選查詢結果。

使用 Join 子句執行內部聯結

  1. 將下列程式碼新增至專案中的 Module1 模組,以查看隱含和明確內部聯結的範例。

    Sub InnerJoinExample()
        ' Create two lists.
        Dim people = GetPeople()
        Dim pets = GetPets(people)
    
        ' Implicit Join.
        Dim petOwners = From pers In people, pet In pets
                        Where pet.Owner Is pers
                        Select pers.FirstName, PetName = pet.Name
    
        ' Display grouped results.
        Dim output As New System.Text.StringBuilder
        For Each pers In petOwners
            output.AppendFormat(
              pers.FirstName & ":" & vbTab & pers.PetName & vbCrLf)
        Next
    
        Console.WriteLine(output)
    
        ' Explicit Join.
        Dim petOwnersJoin = From pers In people
                            Join pet In pets
                            On pet.Owner Equals pers
                            Select pers.FirstName, PetName = pet.Name
    
        ' Display grouped results.
        output = New System.Text.StringBuilder()
        For Each pers In petOwnersJoin
            output.AppendFormat(
              pers.FirstName & ":" & vbTab & pers.PetName & vbCrLf)
        Next
    
        Console.WriteLine(output)
    
        ' Both queries produce the following output:
        '
        ' Magnus:    Daisy
        ' Terry:     Barley
        ' Terry:     Boots
        ' Terry:     Blue Moon
        ' Charlotte: Whiskers
    End Sub
    

使用 Group Join 子句執行左方外部聯結

「左方外部聯結」會包含聯結左側集合中的所有項目,以及合聯結右側集合中僅相符的值。 如果聯結右側集合中有任何項目在左側集合中沒有相符項目,則從查詢結果中排除這些項目。

Group Join 子句實際上會執行「左方外部聯結」。 一般所稱的「左方外部聯結」與 Group Join 子句的差別在於,Group Join 子句會針對聯結左側集合中的每個項目,分組右側集合中的結果。 在關聯式資料庫中,「左方外部聯結」會傳回未分組的結果,其中查詢結果中的每個項目都會包含所聯結兩個集合中的相符項目。 在此情況下,聯結左側集合中的項目會針對右側集合中的每個相符項目重複。 當您完成下一個程序時,您會看到這看起來的樣子。

您可以將 Group Join 查詢的結果作為未分組的結果來擷取,方法是擴充您的查詢,以針對每個分組查詢結果傳回一個項目。 若要達成此目的,您必須確定在分組集合的 DefaultIfEmpty 方法上進行查詢。 這可確保聯結左側集合中的項目即使在右側集合中沒有相符結果,仍會包含在查詢結果中。 您可以將程式碼新增至查詢,以在聯結右側集合中沒有相符的值時提供預設結果值。

使用 Group Join 子句執行左方外部聯結

  1. 將下列程式碼新增至專案中的 Module1 模組,以查看分組左方外部聯結與未分組左方外部聯結的範例。

    Sub LeftOuterJoinExample()
        ' Create two lists.
        Dim people = GetPeople()
        Dim pets = GetPets(people)
    
        ' Grouped results.
        Dim petOwnersGrouped = From pers In people
                               Group Join pet In pets
                                 On pers Equals pet.Owner
                               Into PetList = Group
                               Select pers.FirstName, pers.LastName,
                                      PetList
    
        ' Display grouped results.
        Dim output As New System.Text.StringBuilder
        For Each pers In petOwnersGrouped
            output.AppendFormat(pers.FirstName & ":" & vbCrLf)
            For Each pt In pers.PetList
                output.AppendFormat(vbTab & pt.Name & vbCrLf)
            Next
        Next
    
        Console.WriteLine(output)
        ' This code produces the following output:
        '
        ' Magnus:
        '     Daisy
        ' Terry:
        '     Barley
        '     Boots
        '     Blue Moon
        ' Charlotte:
        '     Whiskers
        ' Arlene:
    
        ' "Flat" results.
        Dim petOwners = From pers In people
                        Group Join pet In pets On pers Equals pet.Owner
                        Into PetList = Group
                        From pet In PetList.DefaultIfEmpty()
                        Select pers.FirstName, pers.LastName,
                               PetName =
                                 If(pet Is Nothing, String.Empty, pet.Name)
    
    
        ' Display "flat" results.
        output = New System.Text.StringBuilder()
        For Each pers In petOwners
            output.AppendFormat(
              pers.FirstName & ":" & vbTab & pers.PetName & vbCrLf)
        Next
    
        Console.WriteLine(output.ToString())
        ' This code produces the following output:
        '
        ' Magnus:	    Daisy
        ' Terry:	    Barley
        ' Terry:	    Boots
        ' Terry:	    Blue Moon
        ' Charlotte:	Whiskers
        ' Arlene:	  
    End Sub
    

使用複合索引鍵執行聯結

您可以使用 JoinGroup Join 子句中的 And 關鍵字來識別多個索引鍵欄位,以在比對聯結集合中的值時使用。 And 關鍵字指定必須符合所有指定的索引鍵欄位,才能聯結項目。

使用複合索引鍵執行聯結

  1. 將下列程式碼新增至專案中的 Module1 模組,以查看使用複合索引鍵的聯結範例。

    Sub CompositeKeyJoinExample()
        ' Create two lists.
        Dim people = GetPeople()
        Dim pets = GetPets(people)
    
        ' Implicit Join.
        Dim petOwners = From pers In people
                        Join pet In pets On
                          pet.Owner.FirstName Equals pers.FirstName And
                          pet.Owner.LastName Equals pers.LastName
                        Select pers.FirstName, PetName = pet.Name
    
        ' Display grouped results.
        Dim output As New System.Text.StringBuilder
        For Each pers In petOwners
            output.AppendFormat(
              pers.FirstName & ":" & vbTab & pers.PetName & vbCrLf)
        Next
    
        Console.WriteLine(output)
        ' This code produces the following output:
        '
        ' Magnus:    Daisy
        ' Terry:     Barley
        ' Terry:     Boots
        ' Terry:     Blue Moon
        ' Charlotte: Whiskers
    End Sub
    

執行程式碼

新增程式碼以執行範例

  1. 將專案中 Module1 模組的 Sub Main 取代為下列程式碼,以執行本主題中的範例。

    Sub Main()
        InnerJoinExample()
        LeftOuterJoinExample()
        CompositeKeyJoinExample()
    
        Console.ReadLine()
    End Sub
    
  2. 按 F5 鍵執行範例。

另請參閱