Realizar combinaciones agrupadasPerform grouped joins

La combinación agrupada resulta útil para generar estructuras de datos jerárquicas.The group join is useful for producing hierarchical data structures. Empareja cada elemento de la primera colección con un conjunto de elementos correlacionados de la segunda colección.It pairs each element from the first collection with a set of correlated elements from the second collection.

Por ejemplo, una clase o una tabla de base de datos relacional denominada Student podría contener dos campos: Id y Name.For example, a class or a relational database table named Student might contain two fields: Id and Name. Una segunda clase o tabla de base de datos relacional denominada Course podría contener dos campos: StudentId y CourseTitle.A second class or relational database table named Course might contain two fields: StudentId and CourseTitle. Una combinación agrupada de estos dos orígenes de datos, basada en la combinación de Student.Id y Course.StudentId, agruparía cada Student con una colección de objetos Course (que podrían estar vacíos).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).

Nota

Cada elemento de la primera colección aparece en el conjunto de resultados de una combinación agrupada, independientemente de si se encuentran elementos correlacionados en la segunda colección.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. En el caso de que no se encuentren elementos correlacionados, la secuencia de elementos correlacionados para ese elemento estaría vacía.In the case where no correlated elements are found, the sequence of correlated elements for that element is empty. Por consiguiente, el selector de resultados tiene acceso a cada uno de los elementos de la primera colección.The result selector therefore has access to every element of the first collection. Esto difiere del selector de resultados en una combinación no agrupada, que no puede acceder a los elementos de la primera colección que no tienen ninguna coincidencia en la segunda colección.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.

En el primer ejemplo de este artículo se muestra cómo realizar una combinación agrupada.The first example in this article shows you how to perform a group join. En el segundo ejemplo se muestra cómo usar una combinación agrupada para crear elementos XML.The second example shows you how to use a group join to create XML elements.

Ejemplo: Combinación agrupadaExample - Group join

En el ejemplo siguiente se realiza una combinación agrupada de objetos de tipo Person y Pet basada en la coincidencia de Person con la propiedad 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. A diferencia de una combinación no agrupada, que generaría un par de elementos para cada coincidencia, la combinación agrupada produce un único objeto resultante para cada elemento de la primera colección, que en este ejemplo es un 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. Los elementos correspondientes de la segunda colección, que en este ejemplo son objetos Pet, se agrupan en una colección.The corresponding elements from the second collection, which in this example are Pet objects, are grouped into a collection. Por último, la función de selector de resultados crea un tipo anónimo para cada coincidencia formada por Person.FirstName y una colección 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:

Ejemplo: Combinación agrupada para crear XMLExample - Group join to create XML

Las combinaciones agrupadas resultan ideales para crear XML con LINQ to XML.Group joins are ideal for creating XML by using LINQ to XML. El siguiente ejemplo es similar al anterior, pero en lugar de crear tipos anónimos, la función de selector de resultados crea elementos XML que representan los objetos combinados.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>

Vea tambiénSee also