Ausführen von inneren Verknüpfungen
Bei relationalen Datenbanken erzeugt eine innere Verknüpfung einen Ergebnissatz, in dem jedes Element der ersten Aufzählung einmal für jedes übereinstimmende Element in der zweiten Auflistung erscheint. Wenn ein Element in der ersten Auflistung keine übereinstimmenden Elemente besitzt, erscheint es nicht im Ergebnissatz. Die Methode Join, die durch die join
-Klausel in C# aufgerufen wird, implementiert eine innere Verknüpfung.
In diesem Artikel erfahren Sie, wie Sie vier Varianten eines inneren Joins ausführen:
Eine einfache innere Verknüpfung, die Elemente aus zwei Datenquellen anhand eines einfachen Schlüssels verknüpft.
Eine innere Verknüpfung, die Elemente aus zwei Datenquellen anhand eines zusammengesetzten Schlüssels verknüpft. Mit einem zusammengesetzten Schlüssel, der aus mehr als einem Wert besteht, können Sie Elemente anhand mehr als einer Eigenschaft verknüpfen.
Eine Mehrfachverknüpfung, in der aufeinanderfolgende Verknüpfungsvorgänge aneinander gehängt werden.
Eine innere Verknüpfung, die mithilfe einer Gruppenverknüpfung implementiert wird.
Hinweis
Die Beispiele in diesem Thema verwenden die folgenden Datenklassen:
record Person(string FirstName, string LastName);
record Pet(string Name, Person Owner);
record Employee(string FirstName, string LastName, int EmployeeID);
record Cat(string Name, Person Owner) : Pet(Name, Owner);
record Dog(string Name, Person Owner) : Pet(Name, Owner);
sowie die Klasse Student
aus Abfragen einer Auflistung von Objekten.
Beispiel: einfacher Schlüsseljoin
Im folgenden Beispiel werden zwei Auflistungen erstellt, die Objekte von zwei benutzerdefinierten Typen (Person
und Pet
) enthalten. Die Abfrage verwendet die join
-Klausel in C#, um Person
-Objekte mit Pet
-Objekten übereinzustimmen, dessen Owner
diese Person
ist. Die select
-Klausel in C# definiert, wie die resultierenden Objekte aussehen werden. In diesem Beispiel sind die resultierenden Objekte anonyme Typen, die aus dem Vornamen des Besitzers und dem Haustiernamen bestehen.
Person magnus = new(FirstName: "Magnus", LastName: "Hedlund");
Person terry = new("Terry", "Adams");
Person charlotte = new("Charlotte", "Weiss");
Person arlene = new("Arlene", "Huff");
Person rui = new("Rui", "Raposo");
List<Person> people = new() { magnus, terry, charlotte, arlene, rui };
List<Pet> pets = new()
{
new(Name: "Barley", Owner: terry),
new("Boots", terry),
new("Whiskers", charlotte),
new("Blue Moon", rui),
new("Daisy", magnus),
};
// Create a collection of person-pet pairs. Each element in the collection
// is an anonymous type containing both the person's name and their pet's name.
var query =
from person in people
join pet in pets on person equals pet.Owner
select new
{
OwnerName = person.FirstName,
PetName = pet.Name
};
foreach (var ownerAndPet in query)
{
Console.WriteLine($"\"{ownerAndPet.PetName}\" is owned by {ownerAndPet.OwnerName}");
}
/* Output:
"Daisy" is owned by Magnus
"Barley" is owned by Terry
"Boots" is owned by Terry
"Whiskers" is owned by Charlotte
"Blue Moon" is owned by Rui
*/
Beachten Sie, dass das Person
-Objekt, dessen LastName
„Huff“ ist, nicht im Ergebnissatz erscheint, weil es kein Pet
-Objekt gibt, bei dem Pet.Owner
gleich Person
ist.
Beispiel: Join mit zusammengesetztem Schlüssel
Anstatt Elemente anhand nur einer Eigenschaft zu verknüpfen, können Sie einen zusammengesetzten Schlüssel verwenden, um Elemente anhand mehreren Eigenschaften zu vergleichen. Geben Sie dazu die Schlüsselauswahlfunktion für jede Auflistung an, um einen anonymen Typ zurückgegeben, der aus den zu vergleichenden Eigenschaften besteht. Wenn Sie die Eigenschaften beschriften, müssen sie über die gleiche Bezeichnung in jedem anonymen Typ des Schlüssels verfügen. Die Eigenschaften müssen auch in der gleichen Reihenfolge angezeigt werden.
Im folgenden Beispiel wird eine Liste von Employee
-Objekten und eine Liste von Student
-Objekten verwendet, um zu bestimmen, welche Angestellten auch Studenten sind. Diese beiden Typen haben eine FirstName
- und LastName
-Eigenschaft vom Typ String. Die Funktion, die die Verknüpfungsschlüssel aus jedem Element der Liste erstellt, gibt einen anonymen Typ zurück, der aus den Eigenschaften FirstName
und LastName
von jedem Element besteht. Der Verknüpfungsvorgang vergleicht diese zusammengesetzten Schlüssel auf Gleichheit und gibt Objektpaare aus jeder Liste zurück, in der der Vor- und Nachname übereinstimmen.
List<Employee> employees = new()
{
new(FirstName: "Terry", LastName: "Adams", EmployeeID: 522459),
new("Charlotte", "Weiss", 204467),
new("Magnus", "Hedland", 866200),
new("Vernette", "Price", 437139)
};
List<Student> students = new()
{
new(FirstName: "Vernette", LastName: "Price", StudentID: 9562),
new("Terry", "Earls", 9870),
new("Terry", "Adams", 9913)
};
// Join the two data sources based on a composite key consisting of first and last name,
// to determine which employees are also students.
var query =
from employee in employees
join student in students on new
{
employee.FirstName,
employee.LastName
} equals new
{
student.FirstName,
student.LastName
}
select employee.FirstName + " " + employee.LastName;
Console.WriteLine("The following people are both employees and students:");
foreach (string name in query)
{
Console.WriteLine(name);
}
/* Output:
The following people are both employees and students:
Terry Adams
Vernette Price
*/
Beispiel: Mehrfachjoin
Eine beliebige Anzahl von Verknüpfungsvorgängen kann aneinander gehängt werden, um eine Mehrfachverknüpfung auszuführen. Jede join
-Klausel in C# verknüpft eine angegebene Datenquelle mit den Ergebnissen der vorherigen Verknüpfung.
Im folgenden Beispiel werden drei Auflistungen erstellt: eine Liste von Person
-Objekten, eine Liste von Cat
-Objekten und eine Liste von Dog
-Objekten.
Die erste join
-Klausel in C# stimmt Personen und Katzen überein, anhand eines Person
-Objekts, das mit Cat.Owner
übereinstimmt. Es gibt eine Sequenz von anonymen Typen zurück, die das Person
-Objekt und Cat.Name
enthält.
Die zweite join
-Klausel in C# verknüpft die von der ersten Verknüpfung zurückgegebenen anonymen Typen mit Dog
-Objekten in der bereitgestellten Liste von Hunden anhand eines zusammengesetzten Schlüssels, der aus der Owner
-Eigenschaft des Person
-Typs und dem ersten Buchstaben des Tiernamens besteht. Sie gibt eine Sequenz von anonymen Typen zurück, die die Eigenschaft Cat.Name
und Dog.Name
von jedem übereinstimmen Paar enthält. Da es sich um eine innere Verknüpfung handelt, werden nur die Elemente aus der ersten Datenquelle zurückgegeben, die eine Übereinstimmung in der zweiten Datenquelle haben.
Person magnus = new(FirstName: "Magnus", LastName: "Hedlund");
Person terry = new("Terry", "Adams");
Person charlotte = new("Charlotte", "Weiss");
Person arlene = new("Arlene", "Huff");
Person rui = new("Rui", "Raposo");
Person phyllis = new("Phyllis", "Harris");
List<Person> people = new() { magnus, terry, charlotte, arlene, rui, phyllis };
List<Cat> cats = new()
{
new(Name: "Barley", Owner: terry),
new("Boots", terry),
new("Whiskers", charlotte),
new("Blue Moon", rui),
new("Daisy", magnus),
};
List<Dog> dogs = new()
{
new(Name: "Four Wheel Drive", Owner: phyllis),
new("Duke", magnus),
new("Denim", terry),
new("Wiley", charlotte),
new("Snoopy", rui),
new("Snickers", arlene),
};
// The first join matches Person and Cat.Owner from the list of people and
// cats, based on a common Person. The second join matches dogs whose names start
// with the same letter as the cats that have the same owner.
var query =
from person in people
join cat in cats on person equals cat.Owner
join dog in dogs on new
{
Owner = person,
Letter = cat.Name.Substring(0, 1)
} equals new
{
dog.Owner,
Letter = dog.Name.Substring(0, 1)
}
select new
{
CatName = cat.Name,
DogName = dog.Name
};
foreach (var obj in query)
{
Console.WriteLine(
$"The cat \"{obj.CatName}\" shares a house, and the first letter of their name, with \"{obj.DogName}\"."
);
}
/* Output:
The cat "Daisy" shares a house, and the first letter of their name, with "Duke".
The cat "Whiskers" shares a house, and the first letter of their name, with "Wiley".
*/
Beispiel: innerer Join mithilfe eines gruppierten Joins
In den folgenden Beispielen wird Ihnen gezeigt, wie eine innere Verknüpfung mithilfe einer Gruppenverknüpfung implementiert wird.
Die Liste von Person
-Objekten in query1
ist über eine Gruppenverknüpfung mit der Liste von Pet
-Objekten verknüpft, basierend auf der Person
, die mit der Eigenschaft Pet.Owner
übereinstimmt. Die Gruppeverknüpfung erstellt eine Auflistung von Zwischengruppen, bei der jede Gruppe aus einem Person
-Objekt und einer Sequenz von übereinstimmenden Pet
-Objekten besteht.
Durch das Hinzufügen einer zweiten from
-Klausel zur Abfrage, wird diese Sequenz von Sequenzen in eine längere Sequenz vereint (oder vereinfacht). Der Typ der Elemente der endgültigen Sequenz wird von der select
-Klausel festgelegt. In diesem Beispiel ist dieser Typ ein anonymer Typ, der aus der Eigenschaft Person.FirstName
und Pet.Name
für jedes übereinstimmende Paar besteht.
Das Ergebnis von query1
entspricht dem Ergebnissatz, der mithilfe der join
-Klausel abgerufen werden würde, ohne dass die into
-Klausel eine innere Verknüpfung ausführt. Die query2
-Variable veranschaulicht diese entsprechende Abfrage.
Person magnus = new(FirstName: "Magnus", LastName: "Hedlund");
Person terry = new("Terry", "Adams");
Person charlotte = new("Charlotte", "Weiss");
Person arlene = new("Arlene", "Huff");
List<Person> people = new() { magnus, terry, charlotte, arlene };
List<Pet> pets = new()
{
new(Name: "Barley", Owner: terry),
new("Boots", terry),
new("Whiskers", charlotte),
new("Blue Moon", terry),
new("Daisy", magnus),
};
var query1 =
from person in people
join pet in pets on person equals pet.Owner into gj
from subpet in gj
select new
{
OwnerName = person.FirstName,
PetName = subpet.Name
};
Console.WriteLine("Inner join using GroupJoin():");
foreach (var v in query1)
{
Console.WriteLine($"{v.OwnerName} - {v.PetName}");
}
var query2 =
from person in people
join pet in pets on person equals pet.Owner
select new
{
OwnerName = person.FirstName,
PetName = pet.Name
};
Console.WriteLine();
Console.WriteLine("The equivalent operation using Join():");
foreach (var v in query2)
{
Console.WriteLine($"{v.OwnerName} - {v.PetName}");
}
/* Output:
Inner join using GroupJoin():
Magnus - Daisy
Terry - Barley
Terry - Boots
Terry - Blue Moon
Charlotte - Whiskers
The equivalent operation using Join():
Magnus - Daisy
Terry - Barley
Terry - Boots
Terry - Blue Moon
Charlotte - Whiskers
*/