无法将null值分配给类型为decimal的成员,该成员是非可空值类型

时间:2013-09-12 06:31:05

标签: c# .net exception linq-to-sql

枚举以下IQueryable时发生异常:

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

错误是InvalidOperationException

  

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

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

3 个答案:

答案 0 :(得分:6)

如果您像这样写了

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)

希望这会对你有所帮助

答案 1 :(得分:3)

LINQ to SQL没有等效地翻译ToDecimal方法;它不能容忍NULL。我使用GetValueOrDefault代替Convert.ToDecimal修正了此问题:

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

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

以下是我对这种情况发生的原因的理解。 LINQ to SQL和Entity Framework提供面值语义转换,而不是 literal 转换。在此示例中,Convert.ToX在SQL中直接转换为CONVERTCAST。这是SQL等效转换,但不是文字,因为它不包含 .NET Convert.ToX操作的详细信息。具体来说,.NET将null转换为默认值。

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

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

答案 2 :(得分:0)

from record in Table
select Convert.ToDecimal(record.nullableDecimalColumn ?? 0);