Share via


Comment : effectuer des jointures internes (Guide de programmation C#)

Mise à jour : novembre 2007

Dans les termes de base de données relationnelle, une jointure interne génère un jeu de résultats dans lequel chaque élément de la première collection apparaît une fois pour chaque élément correspondant dans la deuxième collection. Si un élément de la première collection n'a pas d'éléments correspondants, il n'apparaît pas dans le jeu de résultats. La méthode Join, appelée par la clause join en C# ou la clause Join en Visual Basic, implémente une jointure interne.

Cette rubrique explique comment effectuer quatre variations d'une jointure interne :

  • Une jointure interne simple qui met en corrélation des éléments de deux sources de données selon une clé simple.

  • Une jointure interne qui met en corrélation des éléments de deux sources de données selon une clé composite. Une clé composite, qui est une clé qui se compose de plusieurs valeurs, vous permet de mettre en corrélation des éléments selon plusieurs propriétés.

  • Une jointure multiple dans laquelle les opérations de jointure consécutives sont ajoutées l'une à l'autre.

  • Une jointure interne implémentée en utilisant une jointure groupée.

Exemple

Exemple de jointure de clé simple

L'exemple suivant crée deux collections qui contiennent des objets de deux types définis par l'utilisateur, Person et Pet. La requête utilise la clause join en C# ou la clause Join dans Visual Basic pour faire correspondre des objets Person avec des objets Pet dont Owner est Person. La clause select en C# ou la clause Select dans Visual Basic définit l'apparence des objets résultants. Dans cet exemple, les objets résultants sont des types anonymes qui se composent du prénom du propriétaire et du nom de l'animal domestique.

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("\"{0}\" is owned by {1}", ownerAndPet.PetName, 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

Notez que l'objet Person dont LastName est « Huff » n'apparaît pas dans le jeu de résultats, car aucun objet Pet qui a Pet.Owner n'est égal à Person.

Exemple de jointure de clé composite

Au lieu de mettre en corrélation des éléments selon une seule propriété, vous pouvez utiliser une clé composite pour comparer des éléments selon plusieurs propriétés. Pour ce faire, spécifiez la fonction de sélection de clé de chaque collection pour retourner un type anonyme qui se compose des propriétés vous souhaitez comparer. Si vous étiquetez les propriétés, elles doivent avoir la même étiquette dans le type anonyme de chaque clé. Les propriétés doivent également apparaître dans le même ordre.

L'exemple suivant utilise une liste d'objets Employee et une liste d'objets Student pour déterminer quels employés sont également des étudiants. Ces deux types ont une propriété FirstName et LastName de type String. Les fonctions qui créent les clés de jointure à partir des éléments de chaque liste retournent un type anonyme qui se compose des propriétés FirstName et LastName de chaque élément. L'opération de jointure compare ces clés composites à la recherche d'une égalité et retourne des paires d'objets dans chaque liste présentant une correspondance entre le prénom et le nom.

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

Exemple de jointure multiple

Toutes les opérations de jointure peuvent être ajoutées l'une à l'autre, quelle que soit leur nombre, pour effectuer une jointure multiple. Chaque clause join en C# ou Join dans Visual Basic met en corrélation une source de données spécifiée avec les résultats de la jointure précédente.

L'exemple suivant crée trois collections : une liste d'objets Person, une liste d'objets Cat et une liste d'objets Dog.

La première clause join en C# ou la clause Join dans Visual Basic correspond à des personnes et des chats basés sur un objet Person correspondant à Cat.Owner. Elle retourne une séquence de types anonymes qui contiennent l'objet Person et Cat.Name.

La deuxième clause join en C# ou la clause Join dans Visual Basic met en corrélation les types anonymes retournés par la première jointure avec les objets Dog de la liste de chiens fournie, selon une clé composite qui se compose de la propriété Owner de type Person et de la première lettre du nom de l'animal. Elle retourne une séquence de types anonymes qui contiennent les propriétés Cat.Name et Dog.Name de chaque paire correspondante. Étant donné qu'il s'agit d'une jointure interne, seuls les objets de la première source de données qui ont une correspondance dans la deuxième source de données sont retournés.

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 \"{0}\" shares a house, and the first letter of their name, with \"{1}\".", 
            obj.CatName, 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".

Exemple de jointure interne à l'aide d'une jointure groupée

L'exemple suivant indique comment implémenter une jointure interne en utilisant une jointure groupée.

Dans query1, la liste d'objets Person est jointe par groupe à la liste d'objets Pet en fonction de l'objet Person qui correspond à la propriété Pet.Owner. La jointure groupée crée une collection de groupes intermédiaires où chaque groupe se compose d'un objet Person et d'une séquence d'objets Pet correspondants.

En ajoutant une deuxième clause from (clauseFrom dans Visual Basic) à la requête, cette séquence de séquences est combinée (ou aplatie) dans une séquence plus longue. Le type des éléments de la séquence finale est spécifié par la clause select (clause Select dans Visual Basic). Dans cet exemple, ce type est un type anonyme qui se compose des propriétés Person.FirstName et Pet.Name pour chaque paire correspondante.

Le résultat de query1 est équivalent au jeu de résultats qui aurait été obtenu en utilisant la clause join sans la clause into en C#, ou la clause Join dans Visual Basic, pour effectuer une jointure interne. La variable query2 illustre cette requête équivalente.

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("{0} - {1}", 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("{0} - {1}", 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

Compilation du code

  • Créez un projet d'application console dans Visual Studio.

  • Ajoutez une référence à System.Core.dll si elle n'est pas déjà référencée.

  • Incluez l'espace de noms System.Linq.

  • Copiez et collez le code à partir de l'exemple dans le fichier program.cs, sous la méthode Main. Ajoutez une ligne de code à la méthode Main pour appeler la méthode que vous avez collée.

  • Exécutez le programme.

Voir aussi

Tâches

Comment : effectuer des jointures groupées (Guide de programmation C#)

Comment : effectuer des jointures externes gauches (Guide de programmation C#)

Concepts

Opérations de jointure

Types anonymes

Référence

Join

GroupJoin

Types anonymes (Guide de programmation C#)