LINQ查询表达式(4) - LINQ Join联接

内部联接

  按照关系数据库的说法,“内部联接”产生一个结果集,对于该结果集内第一个集合中的每一个元素,只要在第二个集合中存在一个匹配元素,该元素就会出现一次。 若是第一个集合中的某个元素没有匹配元素,则它不会出如今结果集内。 Join 方法(经过 C# 中的 join 子句调用)可实现内联。数据库

  内部链接的4种变体:函数

  • 简单联接,它基于一个简单的键未来自两个数据源的元素相互关联。
  • 复合联接,它基于一个复合键未来自两个数据源的元素相互关联。 使用复合键(即由多个值组成的键)能够基于多个属性将元素相互关联。
  • 多联接,在其中连续的联接操做被相互拼接在一块儿。
  • 分组联接

  下面分别描述:ui

  1. 内部联接:简单键联接
         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() { // 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 };
         }
  2. 内部联接:复合联接
      与仅仅基于一个属性将元素相互关联不一样,使用复合键可基于多个属性来比较元素。 为此,须要为每一个集合指定键选择器函数,以便返回一个由要比较的属性组成的匿名类型。 若是给属性加上了标签,则这些属性必须在每一个键的匿名类型中都有相同的标签, 并且还必须以相同顺序出现。
    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; }
            }
    
     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;
  3. 内部链接:多联接
        能够将任意数量的联接操做拼接在一块儿以执行多联接。 C# 中的每个 join 子句均可将指定的数据源与前一个联接的结果相互关联。
           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
            { }
    
                // 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 };

     

  4. 内部链接:分组联接实现内部联接
         在 query1 中,Person 对象列表基于与 Pet.Owner 属性匹配的 Person 分组联接到 Pet 对象列表。 分组联接建立了一个中间组集合,该集合中的每一个组都由一个 Person 对象和匹配的 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; }
            }
    
            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 };

    分组联接示例:执行分组联接以建立 XML 的示例spa

    分组联接很是适合于使用 LINQ to XML 来建立 XML。 本例结果选择器函数建立表示已联接对象的 XML 元素,而不是建立匿名类型。code

     class Person
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
        }
        class Pet
        {
            public string Name { get; set; }
            public Person Owner { get; set; }
        }

      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)));  

外部链接

  • 外部联接(左外部联接)

     左外部联接是这样一个联接:在其中返回第一个集合的每一个元素,而不管该元素在第二个集合中是否具备相关元素。 可使用 LINQ 执行左经过对分组联接的结果调用方法 DefaultIfEmpty<TSource> 外部联接链接。对象

        class Person
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
        }

        class Pet
        {
            public string Name { get; set; }
            public Person Owner { get; set; }
        }  

         // 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 query = from person in people
                        join pet in pets on person equals pet.Owner into gj
                        from subpet in gj.DefaultIfEmpty()
                        select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) };
  •  交差联接
       var crossJoinQuery =
                        from c in categories
                        from p in products
                        select new { c.ID, p.Name };
  • 自定义的联接操做
           var nonEquijoinQuery =
                        from p in products
                        let catIds = from c in categories
                                     select c.ID
                        where catIds.Contains(p.CategoryID) == true
                        select new { Product = p.Name, CategoryID = p.CategoryID };

参考

  [1] MSDN,执行内部链接blog

  [2] MSDN,执行分组链接element

相关文章
相关标签/搜索