无法将空值赋给 decimal 类型的成员,因为它是非可空值类型。

8

当以下的IQueryable被枚举时,会发生异常:

from record in dataContext.SomeTable
select Convert.ToDecimal(record.nullableDecimalColumn);

错误是一个"InvalidOperationException":
"null" 值不能分配给类型为 decimal 的成员,decimal 是非可空值类型。
"Convert.ToDecimal" 的文档说明它将 "null" 转换为 "0",因此看起来应该可以正常工作。

Convert.ToDecimal 的文档从未说明在 LINQ-SQL 中它会将 null 转换为 0,我认为这非常具有误导性。 - Suraj Singh
2个回答

9
如果您编写了如下查询:
tot_vat_amt = _pd.Where(x => x.VAT == 4m).Sum(x =>x.amount)

替换为

tot_vat_amt = _pd.Where(x => x.VAT == 4m).Sum(x =>(double?)x.amount)

希望这能对你有所帮助


4
LINQ to SQL无法正确转换ToDecimal方法,它不能容忍NULL。我通过使用GetValueOrDefault代替Convert.ToDecimal解决了这个问题:
from record in dataContext.SomeTable
select record.nullableDecimalColumn.GetValueOrDefault();

这样会导致生成正确的SQL,从而不再出现异常。

我理解的原因是,LINQ to SQL和Entity Framework提供的是表面上的语义转换而不是字面转换。在这个示例中,Convert.ToX直接被翻译成SQL中的CONVERTCAST。这是等效的SQL转换,但它并不是字面意义上的,因为它没有包含.NET Convert.ToX可以操作的细节。具体来说,.NET会将null转换为默认值。

这说明代码并没有表达作者(不是我)真正想做的事情,也就是将null转换为默认值,而不是在数据类型之间进行转换。

在我看来,这也说明了IQueryable是一个有问题的抽象层。我个人认为最好不要使用它,而是使用设计更好的普通/流畅API。我认为IQueryable完全违反了接口隔离原则,因为它允许使用无限范围的查询,尽管只支持有限的子集。


谢谢您的回答,那么实际上会发生什么呢?我的意思是 translated CONVERT 对于 NULL 返回 NULL,它不会将 NULL 转换为任何默认值。是这样吗? - Suraj Singh
我认为可以在SQL中使用ISNULLCOALESCE来处理NULL。而CASTCONVERT则只是用于类型转换。 - Sam
你是否遇到过 CONVERT 函数对于 NULL 值返回 NULL,导致代码出现错误的情况?别担心,你可以通过将鼠标悬停在查询上来检查你的 Linq-SQL 翻译。 - Suraj Singh

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