Linq Coding -- Part Seven (Join之左外部联接、DefaultIfEmpty、GroupJoin)

Join 子句有三种最常见的联接类型:内部联接分组联接,左外部联接
本次介绍:左外部联接,DefaultIfEmpty, GroupJoin

    左外部联接:就是返回第一个集合的每个元素,而无论该元素在第二个集合中是否具有相关元素。可以使用 LINQ,通过对分组联接的

    结果调用 DefaultIfEmpty 来执行左外部联接。

 

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

 

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

 

public void LeftOuterJoinExample()
{
    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 };

 

    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)

                     };
                      //此时subpet为引用类型,所以此时这里是需要进行null检查的。

    foreach (var v in query)
    {
        Console.WriteLine("{0,-15}{1}", v.FirstName + ":", v.PetName);
    }
}

 

DefaultIfEmpty:通过使用延迟执行实现。即时返回值为一个对象,该对象存储执行操作所需的所有信息。

它有两个重载方法:1.返回指定序列的元素;如果序列为空,则返回单一实例集合中的类型参数的默认值。

                               2.返回指定序列中的元素;如果序列为空,则返回单一实例集合中的指定值。

 

public class DefaultIfEmpty
    {
        public void DefaultifEmpty()
//第一种方法重载DEMO
        {
            List<Category> categorys = new List<Category> {
                new Category{ Name="AAAA", ID=11 },
                new Category{ Name="AAAA", ID=13 },
                new Category{ Name="AAAA", ID=14 }
            };

            foreach (Category category in categorys.DefaultIfEmpty())
            {
                Console.WriteLine(category.Name);
            }
        }

        public void EmptyList()
        {
            List<Int32> numbers = new List<Int32>();

            foreach (Int32 number in numbers.DefaultIfEmpty())
            {
                Console.WriteLine(number);
            }
        }

        public void DefaultifEmpty2()//第二种重载DEMO
        {
            Category defcategory = new Category { Name = "AAAA", ID = 13 };

            List<Category> categorys = new List<Category> {
                new Category{ Name="AAAA", ID=11 },
                new Category{ Name="AAAA", ID=13 },
                new Category{ Name="AAAA", ID=14 }
            };

            foreach (Category category in categorys.DefaultIfEmpty(defcategory))
            {
                Console.WriteLine("Name:{0}", category.ID);
            }

            List<Category> categoryEmpty = new List<Category>();

            foreach (Category category in categoryEmpty.DefaultIfEmpty(defcategory))
            {
                Console.WriteLine("Name:{0}", category.Name);
            }
        }

        /*
          11
          13
          14
         
          AAAA
         */

        //从以下的结果可以看出来,
       //如果 source 不为空,是返回List<Category>的数据;
       //如果 source 为空时,则为包含 defaultValue 的 IEnumerable<(Of <(T>)>)。

 }

 

*DefaultIfEmpty()方法与 GroupJoin 方法组合使用,可用于生成左外部联接。

 

GroupJoin:基于键相等对两个序列的元素进行关联并对结果进行分组
GroupJoin同样也有两个重载方法
             1.使用默认的相等比较器 Default 对键进行比较。
             2.使用指定的 IEqualityComparer<(Of <(T>)>) 对键进行比较。

 

 *以下代码执行结果均相同(只是三种不同的写法)

 

public class  GroupJoin    {
        public void groupJoin()
        {
            ///Lamda 写法
            var query =

            Database.people.GroupJoin(Database.pets,
                                    person => person,
                                    pet => pet.Owner,
                                    (person, petCollection) =>
                                    new
                                    {
                                      OwnerName = person.FirstName,
                                      Pets = petCollection.Select(pet => pet.Name)
                                    });

            foreach (var obj in query)
            {
                Console.WriteLine("{0}:", obj.OwnerName);
                foreach (String pet in obj.Pets)
                {
                    Console.WriteLine(" {0}", pet);
                }
            }

            ///结果等同于Lamda
            var queryForLinq2 =
from p in Database.people
                            join pp in Database.pets
                            on p.FirstName equals pp.Owner.FirstName
                            into peoplePets
                            select new
                            {
                              OwnerName = p.FirstName,
                              Pets = peoplePets.Select(pp => pp.Name)
                            };

            ///Linq 写法
           var queryForLinq =
from p in Database.people
                           select new
                           {
                             OwnerName = p.FirstName,
                             Pets = from pp in Database.pets
                                    where p.FirstName == pp.Owner.FirstName
                                    select pp
                           };
            
        }
    }

 

LINQ Coding 目录

  1. Linq Coding -- Part One
  2. Linq Coding -- Part Two[标准查询运算符]
  3. Linq Coding -- Part Three [Let子句]
  4. Linq Coding -- Part Four[Concat应用]
  5. Linq Coding -- Part Five (Join之内部联接查询)
  6. Linq Coding -- Part Six (Join之分组联接)
  7. Linq Coding -- Part Seven (Join之左外部联接、DefaultIfEmpty、GroupJoin)
  8. Linq Coding -- Part Eight (Equals Topic)

转载于:https://www.cnblogs.com/RuiLei/archive/2008/08/19/1271758.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Join操作 适用场景:在我们表关系中有一对一关系,一对多关系,多对多关系等。对各个表之间的关系,就用这些实现对多个表的操作。 说明:在Join操作中,分别为Join(Join查询), SelectMany(Select一对多选择)和GroupJoin(分组Join查询)。 该扩展方法对两个序列中键匹配的元素进行inner join操作 SelectMany 说明:我们在写查询语句时,如果被翻译成SelectMany需要满足2个条件。1:查询语句中没有join和into,2:必须出现EntitySet。在我们表关系中有一对一关系,一对多关系,多对多关系等,下面分别介绍一下。 1.一对多关系(1 to Many): var q = from c in db.Customers from o in c.Orders where c.City == "London" select o; 语句描述:Customers与Orders是一对多关系。即Orders在Customers类中以EntitySet形式出现。所以第二个 from是从c.Orders而不是db.Orders里进行筛选。这个例子在From子句中使用外键导航选择伦敦客户的所有订单。 var q = from p in db.Products where p.Supplier.Country == "USA" && p.UnitsInStock == 0 select p; 语句描述:这一句使用了p.Supplier.Country条件,间接关联了Supplier表。这个例子在Where子句中使用外键导航筛选其供应商在美国且缺货的产品。生成SQL语句为: SELECT [t0].[ProductID], [t0].[ProductName], [t0].[SupplierID], [t0].[CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder],[t0].[ReorderLevel], [t0].[Discontinued] FROM [dbo].[Products] AS [t0] LEFT OUTER JOIN [dbo].[Suppliers] AS [t1] ON [t1].[SupplierID] = [t0].[SupplierID] WHERE ([t1].[Country] = @p0) AND ([t0].[UnitsInStock] = @p1) -- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [USA] -- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [0] 2.多对多关系(Many to Many): var q = from e in db.Employees from et in e.EmployeeTerritories where e.City == "Seattle" select new { e.FirstName, e.LastName, et.Territory.TerritoryDescription }; 说明:多对多关系一般会涉及三个表(如果有一个表是自关联的,那有可能只有2个表)。这一句语句涉及Employees, EmployeeTerritories, Territories三个表。它们的关系是1:M:1。Employees和Territories没有很明确的关系。 LINQ to SQL语句之Join和Order By部分代码 语句描述:这个例子在From子句中使用外键导航筛选在西雅图的雇员,同时列出其所在地区。这条生成SQL语句为: SELECT [t0].[FirstName], [t0].[LastName], [t2].[TerritoryDescription] FROM [dbo].[Employees] AS [t0] CROSS JOIN [dbo].[EmployeeTerritories] AS [t1] INNER JOIN [dbo].[Territories] AS [t2] ON [t2].[TerritoryID] = [t1].[TerritoryID] WHERE ([t0].[City] = @p0) AND ([t1].[EmployeeID] = [t0].[EmployeeID]) -- @p0: Input NVarChar (Siz
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值