Практическое руководство. Объединение данных с помощью LINQ с использованием соединений (Visual Basic)

Visual Basic предоставляет Join предложения и Group Join предложения запросов для объединения содержимого нескольких коллекций на основе общих значений между коллекциями. Эти значения называются ключевыми значениями. Разработчики, знакомые с понятиями реляционной базы данных, будут распознавать Join предложение как INNER JOIN и Group Join предложение как, фактически, LEFT OUTER JOIN.

В примерах в этом разделе показано несколько способов объединения данных с помощью Join предложений запросов и Group Join предложений.

Создание проекта и добавление примеров данных

Создание проекта, содержащего примеры данных и типов

  1. Чтобы запустить примеры в этом разделе, откройте Visual Studio и добавьте новый проект консольного приложения Visual Basic. Дважды щелкните файл Module1.vb, созданный Visual Basic.

  2. В примерах в этом разделе используются Person и типы и Pet данные из следующего примера кода. Скопируйте этот код в модуль по умолчанию Module1 , созданный Visual Basic.

    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

INNER JOIN объединяет данные из двух коллекций. Элементы, для которых включены указанные значения ключей. Все элементы из любой коллекции, у которых нет соответствующего элемента в другой коллекции, исключаются.

В Visual Basic LINQ предоставляет два варианта выполнения INNER JOIN: неявное соединение и явное соединение.

Неявное соединение указывает коллекции, которые необходимо объединить в 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
    

Выполнение левого внешнего соединения с помощью предложения "Объединение групп"

ЭЛЕМЕНТ LEFT OUTER JOIN включает все элементы из левой коллекции соединения и только соответствующие значения из правой коллекции соединения. Все элементы из правой коллекции соединения, которые не имеют соответствующего элемента в левой коллекции, исключаются из результата запроса.

Предложение Group Join выполняет, в действительности, ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ. Разница между тем, что обычно называется left OUTER JOIN и то, что Group Join возвращает предложение, заключается в том, что Group Join группы предложений результаты из правой коллекции соединения для каждого элемента в левой части коллекции. В реляционной базе данных функция LEFT OUTER JOIN возвращает негруппированные результаты, в результате которых каждый элемент в результате запроса содержит соответствующие элементы из обеих коллекций в соединении. В этом случае элементы из левой коллекции соединения повторяются для каждого соответствующего элемента из правой коллекции. После выполнения следующей процедуры вы увидите, как это выглядит.

Результаты Group Join запроса можно получить в виде негруппированного результата, расширив запрос, чтобы вернуть элемент для каждого сгруппированного результата запроса. Для этого необходимо убедиться, что вы запрашиваете DefaultIfEmpty метод сгруппированных коллекций. Это гарантирует, что элементы из левой части коллекции соединения по-прежнему включены в результат запроса, даже если они не имеют соответствующих результатов из правой коллекции. Вы можете добавить код в запрос, чтобы предоставить значение результата по умолчанию, если из правой коллекции соединения нет соответствующего значения.

Выполнение левого внешнего соединения с помощью предложения "Объединение групп"

  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
    

Выполнение соединения с помощью составного ключа

Вы можете использовать And ключевое слово в Join предложении или Group Join для идентификации нескольких ключевых полей, используемых при сопоставлении значений из коллекций, присоединенных. Ключевое слово 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. Замените Sub Main модуль в Module1 проекте следующим кодом, чтобы выполнить примеры в этом разделе.

    Sub Main()
        InnerJoinExample()
        LeftOuterJoinExample()
        CompositeKeyJoinExample()
    
        Console.ReadLine()
    End Sub
    
  2. Нажмите клавишу F5, чтобы запустить примеры.

См. также