Практическое руководство. Выполнение групповых соединений (Руководство по программированию на C#)

Групповое соединение можно использовать для создания иерархических структур данных. Каждый элемент из первой коллекции группируется с набором соответствующих элементов из второй коллекции.

Например, класс или таблица реляционной базы данных под названием Student может содержать два поля: Id и Name. Второй класс или таблица реляционной базы данных под названием Course может содержать два поля: StudentId и CourseTitle. При групповом соединении этих двух источников данных, основанном на сравнении Student.Id и Course.StudentId, приведет к группировке каждого объекта Student с коллекцией объектов Course (которая может быть пустой).

Примечание

Каждый элемент первой коллекции отображается в результирующем наборе группового соединения вне зависимости от того, найдены ли соответствующие ему элементы во второй коллекции.В случае, если такие элементы не найдены, последовательность соответствующих элементов будет пуста.Селектор результата имеет доступ к каждому элементу первой коллекции.При этом следует учесть различие с селектором результата в негрупповом соединении: в этом случае селектор не имеет доступа к элементам из первой коллекции, для которых нет совпадений во второй коллекции.

В первом примере этого раздела показано, как выполнить групповое соединение. Во втором примере — как использовать групповое соединение для создания элементов XML.

Пример

Пример группового соединения

В следующем примере выполняется групповое соединение объектов типа Person и Pet на основе сравнения Person свойства Pet.Owner. В отличие от негруппового соединения, в котором создается пара элементов для каждого точного совпадения, групповое соединение создает результирующий объект для каждого элемента первой коллекции, то есть объекта Person в данном примере. Соответствующие элементы из второй коллекции (в данном примере — объекты Pet) группируются в коллекцию. Результирующая функция селектора создает для каждого совпадения анонимный тип, состоящий из Person.FirstName и коллекции объектов Pet.

        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("{0}:", v.OwnerName);
                // Output each of the owner's pet's names. 
                foreach (Pet pet in v.Pets)
                    Console.WriteLine("  {0}", pet.Name);
            }
        }

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

Применение группового соединения для создания примера XML

Групповое соединение позволяет создавать XML с помощью LINQ to XML. Следующий пример аналогичен предыдущему примеру за исключением того, что вместо создания анонимных типов результирующая функция селектора создает элементы XML, представляющие соединенные объекты. Дополнительные сведения о LINQ to XML см. в разделе LINQ to XML.

        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>

Компиляция кода

  • Создайте в Visual Studio новый проект консольного приложения.

  • Добавьте ссылки на System.Core.dll и System.Xml.Linq.dll, если они отсутствуют.

  • Включите пространства имен System.Linq и System.Xml.Linq.

  • Скопируйте код из примера в файл program.cs ниже метода Main. Добавьте в метод Main строку кода для вызова вставленного метода.

  • Запустите программу.

См. также

Задачи

Практическое руководство. Выполнение внутренних соединений (Руководство по программированию на C#)

Практическое руководство. Выполнение левых внешних соединений (Руководство по программированию на C#)

Ссылки

Join

GroupJoin

Анонимные типы (Руководство по программированию в C#)

Основные понятия

Операции соединения

Анонимные типы (Visual Basic)

Другие ресурсы

LINQ to XML