Практическое руководство. Объединение данных с помощью LINQ с использованием соединений (Visual Basic)
Visual Basic предоставляет Join
предложения и Group Join
предложения запросов для объединения содержимого нескольких коллекций на основе общих значений между коллекциями. Эти значения называются ключевыми значениями. Разработчики, знакомые с понятиями реляционной базы данных, будут распознавать Join
предложение как INNER JOIN и Group Join
предложение как, фактически, LEFT OUTER JOIN.
В примерах в этом разделе показано несколько способов объединения данных с помощью Join
предложений запросов и Group Join
предложений.
Создание проекта и добавление примеров данных
Создание проекта, содержащего примеры данных и типов
Чтобы запустить примеры в этом разделе, откройте Visual Studio и добавьте новый проект консольного приложения Visual Basic. Дважды щелкните файл Module1.vb, созданный Visual Basic.
В примерах в этом разделе используются
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
Добавьте следующий код в
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
метод сгруппированных коллекций. Это гарантирует, что элементы из левой части коллекции соединения по-прежнему включены в результат запроса, даже если они не имеют соответствующих результатов из правой коллекции. Вы можете добавить код в запрос, чтобы предоставить значение результата по умолчанию, если из правой коллекции соединения нет соответствующего значения.
Выполнение левого внешнего соединения с помощью предложения "Объединение групп"
Добавьте следующий код в
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
указывает, что все указанные ключевые поля должны совпадать с элементами, которые должны быть присоединены.
Выполнение соединения с помощью составного ключа
Добавьте следующий код в
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
Запуск кода
Добавление кода для запуска примеров
Замените
Sub Main
модуль вModule1
проекте следующим кодом, чтобы выполнить примеры в этом разделе.Sub Main() InnerJoinExample() LeftOuterJoinExample() CompositeKeyJoinExample() Console.ReadLine() End Sub
Нажмите клавишу F5, чтобы запустить примеры.