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. Но в полученном ProductPriceMinMax мне также нужно свойство таблицы BaseProducts: bp.Name, но он не знает bp.
Любая идея, что я делаю неправильно?
Спасибо!
Ответы
Ответ 1
Как только вы это сделали,
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
};
Тем не менее, это выглядит довольно необычно, и я думаю, вам следует отступить и рассмотреть, что вы на самом деле пытаетесь получить.
Ответ 2
Мы сделали это так:
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
};
EDIT: мы использовали версию AakashM, потому что она имеет лучшую производительность
Ответ 3
Я встретил ту же проблему, что и вы.
Я нажимаю два 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
};