Ausführen von inneren VerknüpfungenPerform inner joins

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.In relational database terms, an inner join produces a result set in which each element of the first collection appears one time for every matching element in the second collection. Wenn ein Element in der ersten Auflistung keine übereinstimmenden Elemente besitzt, erscheint es nicht im Ergebnissatz.If an element in the first collection has no matching elements, it does not appear in the result set. Die Methode Join, die durch die join-Klausel in C# aufgerufen wird, implementiert eine innere Verknüpfung.The Join method, which is called by the join clause in C#, implements an inner join.

In diesem Thema erfahren Sie, wie Sie vier Varianten einer inneren Verknüpfung ausführen:This topic shows you how to perform four variations of an inner join:

  • Eine einfache innere Verknüpfung, die Elemente aus zwei Datenquellen anhand eines einfachen Schlüssels verknüpft.A simple inner join that correlates elements from two data sources based on a simple key.

  • Eine innere Verknüpfung, die Elemente aus zwei Datenquellen anhand eines zusammengesetzten Schlüssels verknüpft.An inner join that correlates elements from two data sources based on a composite key. Mit einem zusammengesetzten Schlüssel, der aus mehr als einem Wert besteht, können Sie Elemente anhand mehr als einer Eigenschaft verknüpfen.A composite key, which is a key that consists of more than one value, enables you to correlate elements based on more than one property.

  • Eine Mehrfachverknüpfung, in der aufeinanderfolgende Verknüpfungsvorgänge aneinander gehängt werden.A multiple join in which successive join operations are appended to each other.

  • Eine innere Verknüpfung, die mithilfe einer Gruppenverknüpfung implementiert wird.An inner join that is implemented by using a group join.

BeispielExample

Beispiel für eine Verknüpfung mit einfachem SchlüsselSimple key join example

Im folgenden Beispiel werden zwei Auflistungen erstellt, die Objekte von zwei benutzerdefinierten Typen (Person und Pet) enthalten.The following example creates two collections that contain objects of two user-defined types, Person and Pet. Die Abfrage verwendet die join-Klausel in C#, um Person-Objekte mit Pet-Objekten übereinzustimmen, dessen Owner diese Person ist.The query uses the join clause in C# to match Person objects with Pet objects whose Owner is that Person. Die select-Klausel in C# definiert, wie die resultierenden Objekte aussehen werden.The select clause in C# defines how the resulting objects will look. In diesem Beispiel sind die resultierenden Objekte anonyme Typen, die aus dem Vornamen des Besitzers und dem Haustiernamen bestehen.In this example the resulting objects are anonymous types that consist of the owner's first name and the pet's name.

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Pet
{
    public string Name { get; set; }
    public Person Owner { get; set; }
}

/// <summary>
/// Simple inner join.
/// </summary>
public static void InnerJoinExample()
{
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };
    Person rui = new Person { FirstName = "Rui", LastName = "Raposo" };

    Pet barley = new Pet { Name = "Barley", Owner = terry };
    Pet boots = new Pet { Name = "Boots", Owner = terry };
    Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
    Pet bluemoon = new Pet { Name = "Blue Moon", Owner = rui };
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

    // Create two lists.
    List<Person> people = new List<Person> { magnus, terry, charlotte, arlene, rui };
    List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy };

    // 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}");
    }
}

// This code produces the following 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.Note that the Person object whose LastName is "Huff" does not appear in the result set because there is no Pet object that has Pet.Owner equal to that Person.

BeispielExample

Beispiel für eine Verknüpfung mit zusammengesetztem SchlüsselComposite key join example

Anstatt Elemente anhand nur einer Eigenschaft zu verknüpfen, können Sie einen zusammengesetzten Schlüssel verwenden, um Elemente anhand mehreren Eigenschaften zu vergleichen.Instead of correlating elements based on just one property, you can use a composite key to compare elements based on multiple properties. Geben Sie dazu die Schlüsselauswahlfunktion für jede Auflistung an, um einen anonymen Typ zurückgegeben, der aus den zu vergleichenden Eigenschaften besteht.To do this, specify the key selector function for each collection to return an anonymous type that consists of the properties you want to compare. Wenn Sie die Eigenschaften beschriften, müssen sie über die gleiche Bezeichnung in jedem anonymen Typ des Schlüssels verfügen.If you label the properties, they must have the same label in each key's anonymous type. Die Eigenschaften müssen auch in der gleichen Reihenfolge angezeigt werden.The properties must also appear in the same order.

Im folgenden Beispiel wird eine Liste von Employee-Objekten und eine Liste von Student-Objekten verwendet, um zu bestimmen, welche Angestellten auch Studenten sind.The following example uses a list of Employee objects and a list of Student objects to determine which employees are also students. Diese beiden Typen haben eine FirstName- und LastName-Eigenschaft vom Typ String.Both of these types have a FirstName and a LastName property of type 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.The functions that create the join keys from each list's elements return an anonymous type that consists of the FirstName and LastName properties of each element. 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.The join operation compares these composite keys for equality and returns pairs of objects from each list where both the first name and the last name match.

class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int EmployeeID { get; set; }
}

class Student
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int StudentID { get; set; }
}

/// <summary>
/// Performs a join operation using a composite key.
/// </summary>
public static void CompositeKeyJoinExample()
{
    // Create a list of employees.
    List<Employee> employees = new List<Employee> {
        new Employee { FirstName = "Terry", LastName = "Adams", EmployeeID = 522459 },
         new Employee { FirstName = "Charlotte", LastName = "Weiss", EmployeeID = 204467 },
         new Employee { FirstName = "Magnus", LastName = "Hedland", EmployeeID = 866200 },
         new Employee { FirstName = "Vernette", LastName = "Price", EmployeeID = 437139 } };

    // Create a list of students.
    List<Student> students = new List<Student> {
        new Student { FirstName = "Vernette", LastName = "Price", StudentID = 9562 },
        new Student { FirstName = "Terry", LastName = "Earls", StudentID = 9870 },
        new Student { FirstName = "Terry", LastName = "Adams", StudentID = 9913 } };

    // Join the two data sources based on a composite key consisting of first and last name,
    // to determine which employees are also students.
    IEnumerable<string> 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);
}

// This code produces the following output:
//
// The following people are both employees and students:
// Terry Adams
// Vernette Price

BeispielExample

Beispiel für eine MehrfachverknüpfungMultiple join example

Eine beliebige Anzahl von Verknüpfungsvorgängen kann aneinander gehängt werden, um eine Mehrfachverknüpfung auszuführen.Any number of join operations can be appended to each other to perform a multiple join. Jede join-Klausel in C# verknüpft eine angegebene Datenquelle mit den Ergebnissen der vorherigen Verknüpfung.Each join clause in C# correlates a specified data source with the results of the previous join.

Im folgenden Beispiel werden drei Auflistungen erstellt: eine Liste von Person-Objekten, eine Liste von Cat-Objekten und eine Liste von Dog-Objekten.The following example creates three collections: a list of Person objects, a list of Cat objects, and a list of Dog objects.

Die erste join-Klausel in C# stimmt Personen und Katzen überein, anhand eines Person-Objekts, das mit Cat.Owner übereinstimmt.The first join clause in C# matches people and cats based on a Person object matching Cat.Owner. Es gibt eine Sequenz von anonymen Typen zurück, die das Person-Objekt und Cat.Name enthält.It returns a sequence of anonymous types that contain the Person object and Cat.Name.

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.The second join clause in C# correlates the anonymous types returned by the first join with Dog objects in the supplied list of dogs, based on a composite key that consists of the Owner property of type Person, and the first letter of the animal's name. Sie gibt eine Sequenz von anonymen Typen zurück, die die Eigenschaft Cat.Name und Dog.Name von jedem übereinstimmen Paar enthält.It returns a sequence of anonymous types that contain the Cat.Name and Dog.Name properties from each matching pair. 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.Because this is an inner join, only those objects from the first data source that have a match in the second data source are returned.

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Pet
{
    public string Name { get; set; }
    public Person Owner { get; set; }
}

class Cat : Pet
{ }

class Dog : Pet
{ }

public static void MultipleJoinExample()
{
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };
    Person rui = new Person { FirstName = "Rui", LastName = "Raposo" };
    Person phyllis = new Person { FirstName = "Phyllis", LastName = "Harris" };

    Cat barley = new Cat { Name = "Barley", Owner = terry };
    Cat boots = new Cat { Name = "Boots", Owner = terry };
    Cat whiskers = new Cat { Name = "Whiskers", Owner = charlotte };
    Cat bluemoon = new Cat { Name = "Blue Moon", Owner = rui };
    Cat daisy = new Cat { Name = "Daisy", Owner = magnus };

    Dog fourwheeldrive = new Dog { Name = "Four Wheel Drive", Owner = phyllis };
    Dog duke = new Dog { Name = "Duke", Owner = magnus };
    Dog denim = new Dog { Name = "Denim", Owner = terry };
    Dog wiley = new Dog { Name = "Wiley", Owner = charlotte };
    Dog snoopy = new Dog { Name = "Snoopy", Owner = rui };
    Dog snickers = new Dog { Name = "Snickers", Owner = arlene };

    // Create three lists.
    List<Person> people =
        new List<Person> { magnus, terry, charlotte, arlene, rui, phyllis };
    List<Cat> cats =
        new List<Cat> { barley, boots, whiskers, bluemoon, daisy };
    List<Dog> dogs =
        new List<Dog> { fourwheeldrive, duke, denim, wiley, snoopy, snickers };

    // 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}\".");  
    }
}

// This code produces the following 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".

BeispielExample

Beispiel einer inneren Verknüpfung mithilfe einer GruppenverknüpfungInner join by using grouped join example

In den folgenden Beispielen wird Ihnen gezeigt, wie eine innere Verknüpfung mithilfe einer Gruppenverknüpfung implementiert wird.The following example shows you how to implement an inner join by using a group join.

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.In query1, the list of Person objects is group-joined to the list of Pet objects based on the Person matching the Pet.Owner property. Die Gruppeverknüpfung erstellt eine Auflistung von Zwischengruppen, bei der jede Gruppe aus einem Person-Objekt und einer Sequenz von übereinstimmenden Pet-Objekten besteht.The group join creates a collection of intermediate groups, where each group consists of a Person object and a sequence of matching Pet objects.

Durch das Hinzufügen einer zweiten from-Klausel zur Abfrage, wird diese Sequenz von Sequenzen in eine längere Sequenz vereint (oder vereinfacht).By adding a second from clause to the query, this sequence of sequences is combined (or flattened) into one longer sequence. Der Typ der Elemente der endgültigen Sequenz wird von der select-Klausel festgelegt.The type of the elements of the final sequence is specified by the select clause. In diesem Beispiel ist dieser Typ ein anonymer Typ, der aus der Eigenschaft Person.FirstName und Pet.Name für jedes übereinstimmende Paar besteht.In this example, that type is an anonymous type that consists of the Person.FirstName and Pet.Name properties for each matching pair.

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.The result of query1 is equivalent to the result set that would have been obtained by using the join clause without the into clause to perform an inner join. Die query2-Variable veranschaulicht diese entsprechende Abfrage.The query2 variable demonstrates this equivalent query.

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Pet
{
    public string Name { get; set; }
    public Person Owner { get; set; }
}

/// <summary>
/// Performs an inner join by using GroupJoin().
/// </summary>
public static void InnerGroupJoinExample()
{
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };

    Pet barley = new Pet { Name = "Barley", Owner = terry };
    Pet boots = new Pet { Name = "Boots", Owner = terry };
    Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
    Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

    // Create two lists.
    List<Person> people = new List<Person> { magnus, terry, charlotte, arlene };
    List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy };

    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("\nThe equivalent operation using Join():");
    foreach (var v in query2)
        Console.WriteLine($"{v.OwnerName} - {v.PetName}"));
}

// This code produces the following 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

Siehe auchSee also

Join
GroupJoin
Ausführen von GruppenverknüpfungenPerform grouped joins
Ausführen linker äußerer VerknüpfungenPerform left outer joins
Anonyme TypenAnonymous types