Executar junções agrupadasPerform grouped joins

A junção de grupo é útil para a produção de estruturas de dados hierárquicos.The group join is useful for producing hierarchical data structures. Ela combina cada elemento da primeira coleção com um conjunto de elementos correlacionados da segunda coleção.It pairs each element from the first collection with a set of correlated elements from the second collection.

Por exemplo, uma classe ou uma tabela de banco de dados relacional chamada Student pode conter dois campos: Id e Name.For example, a class or a relational database table named Student might contain two fields: Id and Name. Uma segunda classe ou tabela de banco de dados relacional chamada Course pode conter dois campos: StudentId e CourseTitle.A second class or relational database table named Course might contain two fields: StudentId and CourseTitle. Uma junção de grupo dessas duas fontes de dados, com base na correspondência de Student.Id e Course.StudentId, agruparia cada Student com uma coleção de objetos Course (que pode estar vazia).A group join of these two data sources, based on matching Student.Id and Course.StudentId, would group each Student with a collection of Course objects (which might be empty).

Observação

Cada elemento da primeira coleção aparece no conjunto de resultados de uma junção de grupo, independentemente de se os elementos correlacionados encontram-se na segunda coleção.Each element of the first collection appears in the result set of a group join regardless of whether correlated elements are found in the second collection. Caso nenhum elemento correlacionado seja encontrado, a sequência de elementos correlacionados desse elemento ficará vazia.In the case where no correlated elements are found, the sequence of correlated elements for that element is empty. O seletor de resultado, portanto, tem acesso a todos os elementos da primeira coleção.The result selector therefore has access to every element of the first collection. Isso difere do seletor de resultado de uma junção que não é de grupo, que não pode acessar os elementos da primeira coleção que não têm correspondência na segunda coleção.This differs from the result selector in a non-group join, which cannot access elements from the first collection that have no match in the second collection.

Aviso

Enumerable.GroupJoin Não tem equivalente direto em termos de banco de dados relacional tradicionais.Enumerable.GroupJoin has no direct equivalent in traditional relational database terms. No entanto, esse método implementa um superconjunto de junções internas e junções externas à esquerda.However, this method does implement a superset of inner joins and left outer joins. Ambas as operações podem ser gravadas em termos de uma junção agrupada.Both of these operations can be written in terms of a grouped join. Para obter mais informações, consulte unir operações e Entity Framework Core, GroupJoin.For more information, see Join Operations and Entity Framework Core, GroupJoin.

O primeiro exemplo neste artigo mostra como executar uma junção de grupo.The first example in this article shows you how to perform a group join. O segundo exemplo mostra como usar uma junção de grupo para criar elementos XML.The second example shows you how to use a group join to create XML elements.

Exemplo – junção de grupoExample - Group join

O exemplo a seguir realiza uma junção de grupo de objetos do tipo Person e Pet com base em Person correspondente à propriedade Pet.Owner.The following example performs a group join of objects of type Person and Pet based on the Person matching the Pet.Owner property. Ao contrário de uma junção que não é de grupo, que produziria um par de elementos para cada correspondência, a junção de grupo produz apenas um objeto resultante para cada elemento da primeira coleção, que neste exemplo é um objeto Person.Unlike a non-group join, which would produce a pair of elements for each match, the group join produces only one resulting object for each element of the first collection, which in this example is a Person object. Os elementos correspondentes da segunda coleção, que neste exemplo são objetos Pet, são agrupados em uma coleção.The corresponding elements from the second collection, which in this example are Pet objects, are grouped into a collection. Por fim, a função de seletor de resultado cria um tipo anônimo para cada correspondência que consiste em Person.FirstName e em uma coleção de objetos Pet.Finally, the result selector function creates an anonymous type for each match that consists of Person.FirstName and a collection of Pet objects.

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>
/// This example performs a grouped join.
/// </summary>
public static void GroupJoinExample()
{
    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 };

    // Create a list where each element is an anonymous type
    // that contains the person's first name and a collection of
    // pets that are owned by them.
    var query = from person in people
                join pet in pets on person equals pet.Owner into gj
                select new { OwnerName = person.FirstName, Pets = gj };

    foreach (var v in query)
    {
        // Output the owner's name.
        Console.WriteLine($"{v.OwnerName}:");
        // Output each of the owner's pet's names.
        foreach (Pet pet in v.Pets)
            Console.WriteLine($"  {pet.Name}");
    }
}

// This code produces the following output:
//
// Magnus:
//   Daisy
// Terry:
//   Barley
//   Boots
//   Blue Moon
// Charlotte:
//   Whiskers
// Arlene:

Exemplo – junção de grupo para criar XMLExample - Group join to create XML

As junções de grupo são ideais para a criação de XML usando o LINQ to XML.Group joins are ideal for creating XML by using LINQ to XML. O exemplo a seguir é semelhante ao exemplo anterior, exceto que em vez de criar tipos anônimos, a função de seletor de resultado cria elementos XML que representam os objetos associados.The following example is similar to the previous example except that instead of creating anonymous types, the result selector function creates XML elements that represent the joined objects.

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>
/// This example creates XML output from a grouped join.
/// </summary>
public static void GroupJoinXMLExample()
{
    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 };

    // Create XML to display the hierarchical organization of people and their pets.
    XElement ownersAndPets = new XElement("PetOwners",
        from person in people
        join pet in pets on person equals pet.Owner into gj
        select new XElement("Person",
            new XAttribute("FirstName", person.FirstName),
            new XAttribute("LastName", person.LastName),
            from subpet in gj
            select new XElement("Pet", subpet.Name)));

    Console.WriteLine(ownersAndPets);
}

// This code produces the following output:
//
// <PetOwners>
//   <Person FirstName="Magnus" LastName="Hedlund">
//     <Pet>Daisy</Pet>
//   </Person>
//   <Person FirstName="Terry" LastName="Adams">
//     <Pet>Barley</Pet>
//     <Pet>Boots</Pet>
//     <Pet>Blue Moon</Pet>
//   </Person>
//   <Person FirstName="Charlotte" LastName="Weiss">
//     <Pet>Whiskers</Pet>
//   </Person>
//   <Person FirstName="Arlene" LastName="Huff" />
// </PetOwners>

Confira tambémSee also