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 目录
- Linq Coding -- Part One
- Linq Coding -- Part Two[标准查询运算符]
- Linq Coding -- Part Three [Let子句]
- Linq Coding -- Part Four[Concat应用]
- Linq Coding -- Part Five (Join之内部联接查询)
- Linq Coding -- Part Six (Join之分组联接)
- Linq Coding -- Part Seven (Join之左外部联接、DefaultIfEmpty、GroupJoin)
- Linq Coding -- Part Eight (Equals Topic)