LINQ:结合连接和分组

我有一个查询,结合了一个连接和一个组,但我有一个问题。 查询如下所示:

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. }; 

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

任何想法我做错了什么?

谢谢!

一旦你完成了这个

 group p by p.SomeId into pg 

您不再有权访问最初使用的范围variables。 也就是说,你不能再谈论pbp ,你只能谈论pg

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

要获得基本的产品名称,您必须在pg组中select一个特定的产品(如您使用SomeIdSomeId ), 然后join到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 }; 

也就是说,这看起来很不寻常,我认为你应该退一步,考虑你实际上想要找回的东西。

我们这样做:

 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 => mpPrice) let maxprice = pg.Max(m => mpPrice) select new ProductPriceMinMax { SomeId = product.SomeId, BaseProductName = baseproduct.Name, CountryCode = product.CountryCode, MinPrice = minprice, MaxPrice = maxprice }; 

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

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

我将两个tables result推入t1对象和组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 };