有人可以解释为什么在以下LINQ查询中发生此异常:
return (from c in dc.Classifications
where c.Id == classificationId
select new Classification()
{
Description = c.Description,
ParentId = Convert.ToInt16(c.ParentId),
}).Single<Classification>();
dc是datacontext,Classification是一个包含int属性ParentId的类 . ParentId列是来自Sql Server数据库的可空int . 如果ParentId字段在数据库中为null,则该语句将返回InvalidOperationException .
换句话说,为什么上面的查询失败并且'int y = Convert.ToInt16(null);'
工作?
3 回答
如果
c.PartentId
可以是null
,则Convert.ToInt16(null)
会抛出异常 .既然你指出
Classification.ParentId
是一个int,你是否有理由使用Convert.ToInt16
来缩短它?你不想要ToInt32吗?就此而言,为什么转换呢?只是:...而且只是为了挑选,从技术上讲,你不需要在Linq表达式的末尾指定你的类型:
你可以省略它,因为它是由编译器决定的,只是这样做:
Update:
哦,我明白了,对不起,我错误地读了你原来的问题 . 问题是为什么:
工作,而Linq2Sql表达式中的相同内容抛出异常 .
我没有一个很好的答案,除了指出虽然表达式在代码中看起来相同,但实际上是由2个不同的Linq实现处理 . (与界面大致相同,可以有不同的后备实现) .
如果是:
您正在直接调用Convert.ToInt16 . 这似乎将null转换为
default<T>
,其中T是所需的类型(因此在这种情况下返回0) .但是,当在Linq2Sql表达式中使用时,表达式及其投影将被移交给Linq2Entities或Linq2Sql进行处理 . 那个地方可能只有一个错误 . 用作基本的Linq2Objects(或者你想要的任何东西)它实际上似乎工作正常:
上面的“选择”工作,但是对Linq2Sql或EntityFramework集合使用相同的Linq表达式将导致Linq处理器的不同实现来处理表达式,并且它可能做一些不同的尝试来表达表达式,或者转向其中一些是SQL语句,或者只是有其他实现没有的错误 .
我知道这并没有真正解决你的问题,但它可能有助于解释它?
假设您希望在数据库中为NULL时将0设为
ParentId
:我的回答还假设,
Classifications.ParentId
的类型为Nullable<int>
/int?
,如果数据库中的列为NULL,则其值为null
.我唯一改变的是转换中的
?? 0
部分 . 如果c.ParentId
为null
,则使用0
,否则为c.ParentId
. 有关详细信息,请参阅?? Operator .c.ParentId的类型为
int?
您对Convert.ToInt16的调用会以两种方式被破坏;它在null上失败(如此处所示),如果ParentId大于short.MaxValue或小于short.MinValue,则失败 .
那为什么打电话?去掉它 . 另外,将
Single<Classification>()
替换为SingleOrDefault()
,以便在适当时返回null .