LINQ查詢表達式(4) - LINQ Join聯接


內部聯接

  按照關系數據庫的說法,“內部聯接”產生一個結果集,對於該結果集內第一個集合中的每個元素,只要在第二個集合中存在一個匹配元素,該元素就會出現一次。 如果第一個集合中的某個元素沒有匹配元素,則它不會出現在結果集內。 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,執行分組連接

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM