我们的初始查询由许多基于使用单列(productId)的连接正常工作的子查询组成。产生的模型映射到一个网格,该网格列出了昨天,今天和明天的产品名称及其各自所需的数量。LINQ多列加入
但是,基于产品的使用年限收到了额外差异因素的要求,因此需要修改原始查询。
因此,以下代码是使用单个字段(ProductId作为关键字)的工作代码的修改。在试图修改查询使用多列密钥(产品编号及年龄)我遇到了麻烦,接收以下错误:
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'GroupJoin'.
在创建不同的集合前面的查询,我改变了关键的复合ProductId和年龄,并将新的匿名类型记忆体productKey设置为新{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}
由于两者都是类型的“B一个new {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 Gods能够看到一个解决方案。对于多列键,而不是使用匿名
当我进行上述更改时,出现错误消息,指出“至少有一个对象必须实现IComparable。”这显示在上述所有查询中,“昨天”,“grp”和“模型”以及未显示的那些查询(“现在”和“明天”),但是与查询“昨天”相同。 – 2011-12-30 08:02:35
@ user946045:IComparable定义了CompareTo方法,它告诉如何比较两个类的实例。这是订购所必需的,但在这种情况下,我认为,最好是按特定列排序 - 更新 – PanJanek 2011-12-30 08:08:27
到目前为止,创建productKey类看起来好像向后退出了2步。当我对最后一个查询中的所有查询使用匿名类型时,每一步都会得到准确的结果。当我使用一个定义的类时,我得到一个IComparable错误,我无法使用Order By子句。 – 2011-12-30 08:40:13