zoukankan      html  css  js  c++  java
  • LINQ查询表达式(4)

    内部联接

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

      内部连接的4种变体:

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

      下面分别描述:

    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 的示例

        分组联接非常适合于使用 LINQ to XML 来创建 XML。 本例结果选择器函数创建表示已联接对象的 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; }
            }
    
          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,执行内部连接

      [2] MSDN,执行分组连接

  • 相关阅读:
    一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——收流篇:(一)简介
    常用perl脚本工具
    一步步学习操作系统(2)——在STM32上实现一个可动态加载kernel的"my-boot"
    一步步学习操作系统(1)——参照ucos,在STM32上实现一个简单的多任务(“啰里啰嗦版”)
    一步步学习操作系统(1)——参照ucos,在STM32上实现一个简单的多任务(“精简版”)
    perl的正则表达式
    vim小技巧
    一些方便的bash命令
    Linux磁盘及文件系统管理
    Linux权限扩展
  • 原文地址:https://www.cnblogs.com/ybtools/p/6559292.html
Copyright © 2011-2022 走看看