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

Обновлен: Ноябрь 2007

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 _firstName As String
      Public _lastName As String
    
      Public Property FirstName() As String
        Get
          Return _firstName
        End Get
        Set(ByVal value As String)
          _firstName = value
        End Set
      End Property
    
      Public Property LastName() As String
        Get
          Return _lastName
        End Get
        Set(ByVal value As String)
          _lastName = value
        End Set
      End Property
    End Class
    
    Class Pet
      Public _name As String
      Public _owner As Person
    
      Public Property Name() As String
        Get
          Return _name
        End Get
        Set(ByVal value As String)
          _name = value
        End Set
      End Property
    
      Public Property Owner() As Person
        Get
          Return _owner
        End Get
        Set(ByVal value As Person)
          _owner = value
        End Set
      End Property
    End Class
    

Выполнение внутреннего соединения с помощью предложения Join

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

В Visual Basic LINQ поддерживает два параметра для выполнения внутреннего соединения: неявное соединение и явное соединение.

Неявное соединение задает коллекции для объединения в предложении From и определяет соответствующие ключевые поля в предложении Where. Visual Basic неявно объединяет две коллекции, основанные на указанных ключевых полях.

Явное соединение можно указать с помощью предложения Join при необходимости явно указать, какие ключевые поля использовать для объединения. В этом случае предложение Where по-прежнему может быть использовано для фильтрации результатов запроса.

Выполнение внутреннего соединения с помощью предложения Join

  • Добавьте следующий код в модуль 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

  • Добавьте следующий код в модуль 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)
    
      ' "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)
      ' This code produces the following output:
      '
      ' Magnus:
      '     Daisy
      ' Terry:
      '     Barley
      '     Boots
      '     Blue Moon
      ' Charlotte:
      '     Whiskers
      ' Arlene:
    
    
      ' 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())
    End Sub
    
    ' This code produces the following output:
    '
    ' Magnus:       Daisy
    ' Terry:        Barley
    ' Terry:        Boots
    ' Terry:        Blue Moon
    ' Charlotte:    Whiskers
    ' Arlene:     
    

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

Можно использовать ключевое слово And в предложении Join или Group Join для идентификации нескольких ключевых полей для использования при определении соответствия значений из соединяемых коллекций. Ключевое слово And определяет, что все указанные ключевые поля должны соответствовать элементам, которые будут присоединены.

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

  • Добавьте следующий код в модуль 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)
    End Sub
    

Запустите код

Добавление кода для выполнения примеров

  1. Чтобы выполнить примеры в этом разделе, замените Sub Main в модуле Module1 в проекте на следующий код.

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

См. также

Основные понятия

Знакомство с LINQ в Visual Basic

Ссылки

Предложение Join (Visual Basic)

Предложение Group Join (Visual Basic)

Условие From (Visual Basic)

Предложение Where (Visual Basic)

Другие ресурсы

LINQ в Visual Basic

Запросы (Visual Basic)