Linq中Join的⽤法
Linq中连接主要有组连接、内连接、左外连接、交叉连接四种。各个⽤法如下。
注:本⽂内容主要来⾃《Linq实战》,本例中⽤到的对象请见⽂章底部。
1、组连接
组连接是与分组查询是⼀样的。即根据分组得到结果。如下例,根据publisther分组得到结果。
使⽤组连接的查询语句如下:
//使⽤组连接
var GroupQuery = from publisher in SampleData.Publishers
join book in SampleData.Books
on publisher equals book.Publisher into publisherBooks
select new
{
PublisherName = publisher.Name,
Books = publisherBooks
};
与上边等同的GroupBy语句如下:
//使⽤Group
var QueryByGroup = from book in SampleData.Books
group book by book.Publisher into grouping
select new
{
PublisherName = grouping.Key.Name,
Books = grouping
};
2、内连接
 按照关系数据库的说法,“内部联接”产⽣⼀个结果集,对于该结果集内第⼀个集合中的每个元素,只要在第⼆个集合中存在⼀个匹配元素,该元素就会出现⼀次。如果第⼀个集合中的某个元素没有匹配元素,则它不会出现在结果集内。
内连接与SqL中inner join⼀样,即出两个序列的交集。如下例出book中的Publisher存在于SampleData.Publishers的资料。
内连接查询语句如下:
//join查询语句
var joinQuery = from publisher in SampleData.Publishers
join book in SampleData.Books
on publisher equals book.Publisher
select new
{
PublisherName = publisher.Name,
BookName = book.Title
};
与上边等同的查询操作符语句如下:
//join操作符语句
SampleData.Publishers.Join(
SampleData.Books,              //join 对象
publisher => publisher,        //外部的key
book => book.Publisher,        //内部的key
(publisher, book) => new        //结果
{
PublisherName = publisher.Name,
BookName = book.Title
});
3、左外连接
左外连接与SqL中left join⼀样。如下例出根据publisher中出SampleData.Publishers中所有资料和book中存在于publisher的资料。
左外连接查询语句如下:
//left join, 为空时⽤default
var leftJoinQuerybyDefault = from publisher in SampleData.Publishers
join book in SampleData.Books
on publisher equals book.Publisher into publisherBooks
from book in publisherBooks.DefaultIfEmpty()
select new
{
PublisherName = publisher.Name,
BookName = (book == default(Book)) ? "no book" : book.Title
};
注:上例中使⽤了DefaultIfEmpty操作符,它能够为实序列提供⼀个默认的元素。DefaultIfEmpty使⽤了泛型中的default关键字。default关键字对于引⽤类型将返回null,⽽对于值类型则返回0。对于结构体类型,则会根据其成员类型将它们相应地初始化为null(引⽤类型)或0(值类型)。
我们可以不使⽤default关键字,但在要DefaultIfEmpty中给定当空时的默认对象值。语句如下:
//left join, 为空时使⽤默认对象
var leftJoinQuery = from publisher in SampleData.Publishers
join book in SampleData.Books
on publisher equals book.Publisher into publisherBooks
from book in publisherBooks.DefaultIfEmpty(
new Book { Title = "" }                        //设置为空时的默认值
)
select new
{
PublisherName = publisher.Name,
BookName = book.Title
};
4、交叉连接
交叉连接与SqL中Cross join⼀样。如下例中出SampleData.Publishers与SampleData.Books的交叉连接。
交叉连接查询语句:
var crossJoinQuery = from publisher in SampleData.Publishers
from book in SampleData.Books
select new
{
PublisherName = publisher.Name,
BookName = book.Title
};
查询操作符语句:
//不使⽤查询表达式
SampleData.Publishers.SelectMany(publisher => SampleData.Books.Select(
book => new
{
PublisherName = publisher.Name,
BookName = book.Title
}
));
本像⽤到的对象:
static public class SampleData
{
static public Publisher[] Publishers =
{
new Publisher {Name="FunBooks"},
new Publisher {Name="Joe Publishing"},
new Publisher {Name="I Publisher"}
};
static public Author[] Authors =
{
new Author {FirstName="Johnny", LastName="Good"},
new Author {FirstName="Graziella", LastName="Simplegame"},      new Author {FirstName="Octavio", LastName="Prince"},
new Author {FirstName="Jeremy", LastName="Legrand"}
};
static public Subject[] Subjects =
{
new Subject {Name="Software development"},
new Subject {Name="Novel"},
new Subject {Name="Science fiction"}
};
static public Book[] Books =
{
new Book {
Title="Funny Stories",
Publisher=Publishers[0],
Authors=new[]{Authors[0], Authors[1]},
PageCount=101,
Price=25.55M,
PublicationDate=new DateTime(2004, 11, 10),
Isbn="0-000-77777-2",
Subject=Subjects[0]
},
new Book {
Title="LINQ rules",
Publisher=Publishers[1],
Authors=new[]{Authors[2]},
PageCount=300,
Price=12M,
PublicationDate=new DateTime(2007, 9, 2),
Isbn="0-111-77777-2",
Subject=Subjects[0]
},
new Book {
Title="C# on Rails",
Publisher=Publishers[1],
Authors=new[]{Authors[2]},
PageCount=256,
Price=35.5M,
PublicationDate=new DateTime(2007, 4, 1),
Isbn="0-222-77777-2",
Subject=Subjects[0]
},
new Book {
Title="All your base are belong to us",
Publisher=Publishers[1],
Authors=new[]{Authors[3]},
join的四种用法PageCount=1205,
Price=35.5M,
PublicationDate=new DateTime(2006, 5, 5),
Isbn="0-333-77777-2",
Subject=Subjects[2]
},
new Book {
Title="Bonjour mon Amour",
Publisher=Publishers[0],
Authors=new[]{Authors[1], Authors[0]},
PageCount=50,
Price=29M,
PublicationDate=new DateTime(1973, 2, 18),        Isbn="2-444-77777-2",
Subject=Subjects[1]
}
};
}