LINQ to SQL与空值

5

I have the following LINQ to SQL query:

var inTransitStocks = orderHistories.Where(oh => oh.Shipped_Qty > 0)
                                    .Select(oh => oh.Shipped_Qty); //.ToList();
var inTransitStock = (int)inTransitStocks.Sum();

没有调用ToList时,在Sum()行会出现以下异常:

不能将 null 值分配给类型为 System.Double 的非空值类型成员。

如果我在 sum 之前添加一个 .ToList()(如注释中所示),就不会出现错误。 为什么我会首先出现这个错误?Shipped_Qty 不为空,该字段中也不存在 null 数据) 为什么添加ToList()可以解决问题?
执行的 SQL 查询如下(查询内容不止上面所示):
SELECT [t0].[Shipped Qty]
FROM [dbo].[Order History] AS [t0]
WHERE ([t0].[Shipped Qty] > @p0) AND ([t0].[CUST_ID] = @p1) AND ([t0].[SHIP_TO_ID] = @p2) AND ([t0].[Item] = @p3) AND (([t0].[DT_LST_SHP] >= @p4) OR (UNICODE([t0].[LN_STA]) = @p5))

未返回任何结果。


4
这个问题在很久以前就被问过了,没有什么可以总结的。将其改写为 inTransitStocks.Sum(x => (int?)x) ?? 0,它应该能够运行。 - Giedrius
3个回答

6
原因如下:
没有使用ToList,以下查询将针对数据库执行:
select SUM(Shipped_Qty) from orderHistories where Shipped_Qty > 0;

如果没有符合此条件的行,则此查询的结果不是0,而是NULL
使用ToList执行以下查询:
select Shipped_Qty from orderHistories where Shipped_Qty > 0;

查询结果(没有行)将被放入列表中。结果是一个空列表。在这个空列表上执行LINQ to Objects扩展方法Sum。空列表的总和为0而不是null

因此,基本上:不同的语义导致不同的结果。


这就是我之前没有理解的地方,我本来期望没有结果会返回一个非NULL值,因为NULL有可能是一个合法的返回值。 - George Duckett
1
在SQL中,SUM仅在两种情况下返回NULL:(1)没有行可求和或(2)至少有一行要求和的值为NULL。 - Daniel Hilgarth
谢谢,这就是我没有理解的关键点,我期望在对零行求和时得到零行,而不是一个空值。 - George Duckett

0
在执行ToList()之后,您正在使用Linq-To-Objects实现的Sum
在执行ToList()之前,Sum操作被聚合到Linq-To-Sql查询中。

如果想找出 Linq-To-Sql 失败的原因,请参考Daniel Hilgath 的方法


0

所有的话都已经说过了,但让我重新表述一下:这是因为 var 的神奇之处!

Without ToList() var <=> DbQuery
With ToList() var <=> List<Double>

Sum函数在这两种类型上的行为不同...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接