LINQ学习笔记:选取Select(6)
http://www.itjxue.com 2015-07-17 01:59 来源:未知 点击次数:
SelectMany和Outer join
在前面使用select的left outer join例子中:
1: from c in dataContext.Customers
2:
3: select new {
4:
5: c.Name,
6:
7: Purchases =
8:
9: from p in c.Purchases
10:
11: where p.Price > 1000
12:
13: select new { p.Description, p.Price }
14:
15: };
每一个客户都会被包括,不管它是否包含任何订单. 假设我们现在要使用SelectMany重新编写这个查询:
1: from c in dataContext.Customers
2:
3: from p in c.Purchases
4:
5: where p.Price > 1000
6:
7: select new { c.Name, p.Description, p.Price };
然而这个查询得到的是一个inner join的效果,只有包含Price>1000的采购单的客户才会被包括进来. 为了能够得到一个left outer join结果,我们可以在内部序列上使用DefaultIfEmpty查询操作符,此方法对于没有包含任何元素的输入序列返回null:
1: from c in dataContext.Customers
2:
3: from p in c.Purchases.DefaultIfEmpty()
4:
5: select new {
6:
7: c.Name,
8:
9: p.Description,
10:
11: Price = (decimal?) p.Price
12:
13: };
这个查询在LINQ to SQL当中工作良好,并且将会返回所有的客户即便他们不包含任何的采购单. 但对于本次查询,当p等于null的时候将会得到一个NullReferenceException异常, 不过我们还是可以进一步完善它:
1: from c in dataContext.Customers
2:
3: from p in c.Purchases.DefaultIfEmpty( )
4:
5: select new
6:
7: {
8:
9: c.Name,
10:
11: Descript = p == null ? null : p.Description,
12:
13: Price = p == null ? (decimal?) null : p.Price
14:
15: };
接下来让我们引出Price过滤器,我们不能简单的像以前做的那样直接加上where语句,因为它会在DefaultIfEmpty之后执行,正确的解决方案是我们需要一个子查询并且必须让Where语句在DefaultIfEmpty之前:
1: from c in dataContext.Customers
2:
3: from p in c.Purchases.Where (p => p.Price > 1000)
4:
5: .DefaultIfEmpty( )
6:
7: select new
8:
9: {
10:
11: c.Name,
12:
13: Descript = p == null ? null : p.Description,
14:
15: Price = p == null ? (decimal?) null : p.Price
16:
17: };
这个查询在LINQ to SQl当中将会被很好的转换成left outer join, 并且对于编写这类型的查询这是一个比较有效率的做法. 待续!
(责任编辑:IT教学网)
上一篇:LINQ学习笔记:聚合方法
下一篇:LINQ学习笔记:创建方法