グループ結合の実行Perform grouped joins

グループ結合は、階層データ構造を作成する場合に便利です。The group join is useful for producing hierarchical data structures. これは、最初のコレクションの各要素と、2 番目のコレクションの相関関係を持つ要素のセットを組み合わせたものです。It pairs each element from the first collection with a set of correlated elements from the second collection.

たとえば、Student という名前のクラスまたはリレーショナル データベース テーブルに、IdName という 2 つのフィールドが含まれているとします。For example, a class or a relational database table named Student might contain two fields: Id and Name. Course という名前の 2 番目のクラスまたはリレーショナル データベース テーブルには、StudentIdCourseTitle という 2 つのフィールドが含まれているとします。A second class or relational database table named Course might contain two fields: StudentId and CourseTitle. この 2 つのデータ ソースのグループ結合は、Student.IdCourse.StudentId の一致に基づいて、Course オブジェクトのコレクションを持つ各 Student をグループ化します (コレクションは空の場合もあります)。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).

注意

最初のコレクションの各要素は、2 番目のコレクションに相関関係を持つ要素があるかどうかにかかわらず、グループ結合の結果セットに表示されます。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. 相関関係を持つ要素が見つからない場合、その要素の相関関係を持つ要素のシーケンスは空です。In the case where no correlated elements are found, the sequence of correlated elements for that element is empty. そのため、結果セレクターは最初のコレクションのすべての要素にアクセスできます。The result selector therefore has access to every element of the first collection. これは、非グループ結合の結果セレクターとは異なります。非グループ結合の結果セレクターは、2 番目のコレクションに一致するものがない最初のコレクションの要素にアクセスすることはできません。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.

この記事の最初の例では、グループ結合を実行する方法を示します。The first example in this article shows you how to perform a group join. 2 つ目の例では、グループ結合を使用して XML 要素を作成する方法を示します。The second example shows you how to use a group join to create XML elements.

例 - グループ結合Example - Group join

次の例では、Pet.Owner プロパティと一致する Person に基づいて、Person 型と Pet 型のオブジェクトのグループ結合を実行します。The following example performs a group join of objects of type Person and Pet based on the Person matching the Pet.Owner property. 一致ごとに要素のペアを生成する非グループ結合と異なり、グループ結合は最初のコレクションの要素ごとに 1 つのオブジェクト (この例では 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. 2 番目のコレクションの対応する要素 (この例では Pet オブジェクト) が 1 つのコレクションにグループ化されます。The corresponding elements from the second collection, which in this example are Pet objects, are grouped into a collection. 最後に、結果セレクター機能により、Person.FirstName と、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:

例 - XML を作成するグループ結合Example - Group join to create XML

グループ結合は、LINQ to XML を使用した XML の作成に適しています。Group joins are ideal for creating XML by using LINQ to XML. 次の例は前の例に似ていますが、匿名型を作成するのではなく、結果セレクター機能により、結合されたオブジェクトを表す XML 要素を作成する点が異なります。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>

関連項目See also