对于我们在内存集合中使用的单元测试来验证LINQ查询的逻辑。但是,在下面的场景中,我看到了LINQ to SQL vs In Memory的结果之间的差异。DefaultIfEmpty - LINQ to SQL vs In Memory
对于这个例子,我们有三个表Customer,Order,Item。我希望客户订购的所有物品的数量。我想向那些还没有订购任何物品的顾客展示。在SQL中,这将是一个外连接。在LINQ to SQL中,我写了这个...
var itemCounts =
from c in Customer
from o in Order.Where(oo=>o.CustomerId==c.CustomerId).DefaultIfEmpty()
from i in Item.Where(ii=>i.OrderId==o.OrderId).DefaultIfEmpty()
group i by new { i.ItemId, c.CustomerId } into ig
select new ItemCountResult {
CustomerId = ig.Key.CustomerId,
Count = ig.Count()
};
这对我们违背数据库时正常工作。我们获得客户的订单和没有订单的数量。当我们将内存集合替换为单元测试时,我们看到对象引用未设置异常。我已经缩小到“i.OrderId == o.OrderId”这一行,具体说o是空的。
根据“DefaultIfEmpty”的工作方式,这实际上是我期望的行为。 DefaultIfEmpty返回一个枚举为null的单个元素。
那么我该如何解决这段代码在两种情况下工作?
更新: 虽然我简化了问题,但我丢失了一些重要的信息。所以让我重申一下这个问题。
客户有0-n个订单。 订单有1-n个项目。 一个项目有1-n个订单。
我需要项目列表以及订购该项目的客户数量。如果0位顾客订购了我想要的产品,但它仍然返回,但计数为0.
问题是Order和Item之间的多对多阻止我使用join-into语法。
我现在有这样的事(希望没有输入错误时这段时间):
var counts =
from i in Items
from oi in OrderItems.Where(z=>z.ItemId==i.ItemId).DefaultIfEmpty()
from o in Orders.Where(z=>z.OrderId==oi.OrderId).DefaultIfEmpty()
from c in Customers.Where(z=>z.CustomerId==o.CustomerId).DefaultIfEmpty()
group c by new { i.ItemId, c.CustomerId } into cg
select new CountResult {
CustomerId = cg.Key.CustomerId,
Count = cg.Count()
};
当我简化我拼写错误的O问题vs oo。我也遗漏了我们的关系。 Order to Item实际上是多对多而不是一对多的。抱歉。你是正确的,但交替的加入语法可以解决问题。但是我无法在多对多的情况下工作。我会在上面更新我的问题。 – joegtp 2011-04-12 17:25:01