Наш первоначальный запрос состоит из множества подзапросов, которые работают правильно, на основе объединений, которые используют один столбец (productId). Полученная модель отображает сетку, в которой перечислены названия продуктов вместе с соответствующими требуемыми количествами для вчера, сегодня и завтра.LINQ Multiple Column Join
Однако требование было получено для дополнительного дифференциатора в зависимости от возраста продукта, и поэтому необходимо было изменить исходный запрос.
Таким образом, следующий код представляет собой модификацию рабочего кода, который использует одно поле, ProductId в качестве ключа. При попытке изменить запрос, чтобы использовать несколько ключ столбца (ProductID и возраст), я столкнулся с проблемой, получаем следующее сообщение об ошибке:
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'GroupJoin'.
В предыдущем запросе, который создает Distinct Aggregate, я изменил ключ к композиту ProductId и возраст и назначить нового члена анонимного типа, productKey - new {pr.productId, pr.age}. Затем в последнем запросе я пытаюсь присоединиться к этому результату на productKey равно new {y.productId, y.age} (y представляет собой результат соединения «вчера»).
Когда я парить над каждым из ключей соединенных результатов (gr.productKey и y.productKey), следующее отображается для каждого:
'b 'a.productKey
Anonymous Types:
'a is new {'b productKey, int productId, string age,... }
'b is new {int productId, string age}
Поскольку оба типа «б в новый {int productId, string age} Я ожидал успеха; однако компилятор продолжает отказываться. Я верю, что один новый {int, string} - это то же самое, что и другое, не имеющее имен.
var yesterday = from p in productOrdered
where p.deliveryDate.Date == DateTime.Now.AddDays(-1).Date
group p by new { p.id, p.age } into g
orderby g.Key
select new {
productKey = g.Key,
productId = g.Max(s => s.id),
age = g.Max(s => s.age),
quantity = g.Count(),
weight = g.Sum(s => s.weight),
};
var grp = (from pr in prods2
group pr by new { pr.productId, pr.age } into g
orderby g.Key
select new {
productKey = g.Key,
productId = g.Max(s => s.productId),
age = g.Max(s => s.age),
code = g.Max(s => s.code),
product = g.Max(s => s.product),
uom = g.Max(s => s.uom)
}).Distinct();
var model = from gr in grp
join y in yesterday on gr.productKey equals new { y.productId, y.age } into outer0
from y in outer0.DefaultIfEmpty()
join n in now on gr.productKey equals new { n.productId, n.age } into outer1
from n in outer1.DefaultIfEmpty()
join t in tomorrow on gr.productKey equals new { t.productId, t.age } into outer2
from t in outer2.DefaultIfEmpty()
select new RequiredProductsViewModel
{
ProductId = gr.productId,
Aged = gr.age,
Code = gr.code.ToString(),
Description = gr.product.ToString(),
MinusQ = (!(null == y) ? y.quantity : 0),
MinusW = (!(null == y) ? decimal.Parse(y.weight.ToString()) : 0),
ZeroQ = (!(null == n) ? n.quantity : 0),
ZeroW = (!(null == n) ? decimal.Parse(n.weight.ToString()) : 0),
OneQ = (!(null == t) ? t.quantity : 0),
OneW = (!(null == t) ? decimal.Parse(t.weight.ToString()) : 0),
UofM = gr.uom.ToString()
};
Тестирование в LINQPad привело к аналогичным результатам, и я также попытался несколько вариаций на основе подобных вопросов на этом сайте, такие как, но не ограничиваясь следующим:
join y in yesterday on new {Key1 = gr.productId,Key2 = gr.age} equals y.productKey into outer0
join y in yesterday on new { gr.productId, gr.age } equals y.productKey into outer0
Опять же, исходный запрос, что это модификация успешно работает. Я уверен, что это одна из тех проблем, которые «мало знают, являются опасными». Или, может быть, просто «небольшое знание». В любом случае, я надеюсь, что боги LINQ смогут увидеть решение.
Когда я делаю вышеуказанные изменения, я получаю сообщение об ошибке «По крайней мере, один объект должен реализовать IComparable». Это отображается во всех вышеперечисленных запросах: «вчера», «grp» и «model», а также те запросы, которые не показаны («сейчас» и «завтра»), но такие же, как и запрос «вчера». –
@ user946045: IComparable определяет метод CompareTo, который рассказывает, как сравнивать два экземпляра класса. Это необходимо для заказа, но в этом случае, я думаю, было бы лучше заказать конкретный столбец - обновлено aswer – PanJanek
Ну, пока что создание класса productKey, похоже, делает 2 шага назад. Когда я использую анонимный тип для всех запросов, предшествующих последним, я получаю точные результаты на каждом шаге. Когда я использую определенный класс, я получаю IComparable ошибку, ни в коем случае я использую предложение Order By. –