不能将 null 值分配给类型为 decimal 的成员,该成员是不可为空的值类型

本文关键字:类型 成员 decimal null 分配 不能 | 更新日期: 2023-09-27 18:31:04

枚举以下IQueryable时发生异常:

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

错误是一个InvalidOperationException

不能将 null 值分配给类型为 decimal 的成员,该成员是不可为空的值类型

Convert.ToDecimal的文档说它将null转换为 0 ,因此看起来它应该可以正常工作。

不能将 null 值分配给类型为 decimal 的成员,该成员是不可为空的值类型

如果你这样写查询

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)

希望这对你有帮助

LINQ to SQL并没有等效地转换ToDecimal方法;它不能容忍NULL。我通过使用GetValueOrDefault而不是Convert.ToDecimal来解决此问题:

from record in dataContext.SomeTable
select record.nullableDecimalColumn.GetValueOrDefault();

这导致生成正确的 SQL,因此不再发生异常。

以下是我对为什么会发生这种情况的理解。LINQ to SQL 和实体框架提供表面值语义翻译,而不是文字翻译。在此示例中,Convert.ToX直接转换为 SQL 中的CONVERTCAST。这是 SQL 等效的翻译,但不是文字翻译,因为它不包括 .NET Convert.ToX如何运行的细节。具体来说,.NET 将 null s 转换为默认值。

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

在我看来,这也是IQueryable是一个泄漏和不可靠的抽象的症状。我个人认为最好不要首先使用它,而是使用设计得更好的东西,例如普通/流畅的 API。我认为IQueryable完全违反了接口隔离原则,因为它允许使用无限范围的查询,尽管只支持有限的子集。