LINQ:结合join和group by

L-F*_*our 51 c# linq join group-by linq-to-sql

我有一个结合了连接和组的查询,但我遇到了问题.查询如下:

 var result = from p in Products                         
 join bp in BaseProducts on p.BaseProductId equals bp.Id                    
 group p by p.SomeId into pg                         
 select new ProductPriceMinMax { 
       SomeId = pg.FirstOrDefault().SomeId, 
       CountryCode = pg.FirstOrDefault().CountryCode, 
       MinPrice = pg.Min(m => m.Price), 
       MaxPrice = pg.Max(m => m.Price),
       BaseProductName = bp.Name  <------ can't use bp. 
 };
Run Code Online (Sandbox Code Playgroud)

如您所见,它将Products表与BaseProducts表连接,并在Product表的id上加入组.但是在生成的ProductPriceMinMax中,我还需要BaseProducts表的一个属性:bp.Name,但它不知道bp.

知道我做错了什么吗?

谢谢!

Aak*_*shM 88

一旦你完成了这个

group p by p.SomeId into pg  
Run Code Online (Sandbox Code Playgroud)

您无法再访问初始中使用的范围变量from.也就是说,你不能再谈论p或者bp,你只能谈论pg.

现在,pg是一个群组,因此包含多个产品.给定pg组中的所有产品都具有相同的SomeId(因为这是您分组的),但我不知道这是否意味着它们都具有相同的功能BaseProductId.

为了得到一个基本产品的名称,你必须选择特定产品pg组(如你有做SomeIdCountryCode),并随后加盟BaseProducts.

var result = from p in Products                         
 group p by p.SomeId into pg                         
 // join *after* group
 join bp in BaseProducts on pg.FirstOrDefault().BaseProductId equals bp.Id         
 select new ProductPriceMinMax { 
       SomeId = pg.FirstOrDefault().SomeId, 
       CountryCode = pg.FirstOrDefault().CountryCode, 
       MinPrice = pg.Min(m => m.Price), 
       MaxPrice = pg.Max(m => m.Price),
       BaseProductName = bp.Name  // now there is a 'bp' in scope
 };
Run Code Online (Sandbox Code Playgroud)

也就是说,这看起来很不寻常,我认为你应该退后一步,考虑一下你实际想要检索的内容.


L-F*_*our 26

我们这样做了:

from p in Products                         
join bp in BaseProducts on p.BaseProductId equals bp.Id                    
where !string.IsNullOrEmpty(p.SomeId) && p.LastPublished >= lastDate                         
group new { p, bp } by new { p.SomeId } into pg    
let firstproductgroup = pg.FirstOrDefault()
let product = firstproductgroup.p
let baseproduct = firstproductgroup.bp
let minprice = pg.Min(m => m.p.Price)
let maxprice = pg.Max(m => m.p.Price)
select new ProductPriceMinMax
{
SomeId = product.SomeId,
BaseProductName = baseproduct.Name,
CountryCode = product.CountryCode,
MinPrice = minprice, 
MaxPrice = maxprice
};
Run Code Online (Sandbox Code Playgroud)

编辑:我们使用了AakashM的版本,因为它具有更好的性能


小智 11

我遇到了和你一样的问题.

我把两个推tables resultt1对象和组t1.

 from p in Products                         
  join bp in BaseProducts on p.BaseProductId equals bp.Id
  select new {
   p,
   bp
  } into t1
 group t1 by t1.p.SomeId into g
 select new ProductPriceMinMax { 
  SomeId = g.FirstOrDefault().p.SomeId, 
  CountryCode = g.FirstOrDefault().p.CountryCode, 
  MinPrice = g.Min(m => m.bp.Price), 
  MaxPrice = g.Max(m => m.bp.Price),
  BaseProductName = g.FirstOrDefault().bp.Name
};
Run Code Online (Sandbox Code Playgroud)