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教学网)

更多

推荐ASP.NET教程文章