LINQ:组合联接和分组依据
本文关键字:组合 LINQ | 更新日期: 2023-09-27 18:22:44
我有一个结合了联接和组的查询,但我有一个问题。查询如下所示:
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
您不再有权访问初始from
中使用的范围变量。也就是说,你不能再谈论p
或bp
,你只能谈论pg
。
现在,pg
是一个组,因此包含多个产品。给定pg
组中的所有产品都具有相同的SomeId
(因为这是您分组的依据(,但我不知道这是否意味着它们都具有相同的BaseProductId
。
要获取基本产品名称,您必须在pg
组中选择一个特定产品(就像您对 SomeId
和 CountryCode
所做的那样(,然后加入 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 => 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
};
编辑:我们使用了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
};