2013-03-14 54 views
2

我有一个可空DateTime字段“出生日期”的现有代码以这样的方式解释处理DBNull?

info.BirthDate = (DateTime?)reader["Birthdate"]; 

这会导致“无效的转换”错误和它打破了这个HANDELING。好吧,我明白这是因为空值从SQL返回不同,是类型“DBNull的”

定为这竟然是

if (reader["Birthdate"] != DBNull.Value) 
{ 
    info.Birthdate = (DateTime)reader["Birthdate"]; 
} 

有人能解释到底为什么这个工程?我特别是在DBNull的.Value部分丢失了。如果它返回为DBNull IS代码甚至可以在这个块内到达吗?

回答

4

DBNull是一个单身人士。它只有一个实例。您可以使用DBNull.Value访问此实例。比较检查是否返回DBNull(.Value),如果没有返回(!=),则知道它可以安全地将其转换为DateTime

MSDN

的DBNull是一个单独的类,这意味着这个 类的只有这个实例可以存在。

另外,您可以使用Convert.IsDBNull方法:

if (!Convert.IsDBNull(reader["Birthdate"])) 
{ 
    info.Birthdate = (DateTime)reader["Birthdate"]; 
} 
+0

.... OH。好吧,因为这个属性是可以空的,所以它没有任何内容,并且这个块被跳过。我现在明白了。谢谢! – Evr 2013-03-14 15:58:22

+0

第三个选项是'reader [“Birthdate”]作为DateTime?'。 (对第三种选择有有效的反对意见,并且也有赞成的有效论据,我宁愿避免这样的讨论:)) – hvd 2013-03-14 15:58:23

+0

啊,对了,会的。说我可以在4分钟内。这是我第一篇帖子SO – Evr 2013-03-14 16:01:31

0

DBNull是一个类型,而不是一个。正如@aKzenT所解释的那样,它是作为单例实现的,这意味着该类型只能有一个实例。达到该值的方法是通过静态.Value属性。

这使得它容易做比较,因为任何DBNull实例的值和参考另一个DBNull实例都是相等的。

另一种方式来做到这一点支票可能更有意义的是:

int columnIndex = reader.GetOrdinal("Birthdate"); 
if (!reader.IsDbNull(columnIndex)) // IsDbNull should have a string overload, but it does not. 
{ 
    info.Birthdate = (DateTime)reader["Birthdate"]; 
} 
+0

谢谢你的补充澄清!..很高兴我决定在这里发帖,而不是无知地想。 – Evr 2013-03-14 16:06:35