2011-11-07 18 views
4

我正在寻找一些.net程序的代码,我正在处理。该程序的前一作者在一年前向我提供了代码。突然,我看到从代码中抛出的异常,我没有感动:关于空字符串和DBNull的困惑

if ((string)row["LevelName"] != "ABC") 

唯一的例外是“无法投类型的对象'System.DBNull为键入‘System.String’

我认为字符串是一个可空数据类型,所以我怎么可能会得到这个异常

+0

此代码已运行良好超过一年;我觉得我一定在某个地方弄错了什么 –

+0

是的,事实上,我做到了。有问题的代码没有准备好DBNull值,因为它永远不会出现在我正在运行的特定查询中。我在修改查询时犯了一个错误,因此错误出现了。 –

+0

感谢您提供丰富的答案,每个人。我把它们都投了票。难怪我读的SQL书叫NULL“四个字母的单词”。 –

回答

7

DBNull是它自己的类,它包含itsself在一个名为Value属性singleton实例。 DBNull.Value不等于null,因为它是对此类的实例的引用。

如果没有值,大多数(即使不是全部)数据库包装将返回DBNull.Value而不是null。其中一个原因是因为返回一个真实的null可能意味着根本不存在任何行,而不仅仅是列中的空值(这取决于您使用哪些对象来获取值)。

通常,as运算符对于DBNull非常有用,可以与任何可空类型(包括string)一起使用。

string str = reader["Name"] as string; 
int? i = reader["Age"] as int?; 

这也可能是值得一提的是,??运营商是非常有用的也在这里,当你需要一个非空值类型(虽然它不看太漂亮)。

int i = reader["Age"] as int? ?? -1; 

我发现这很方便,因为它是LINQ select子句中的一件小事。

+0

我很害怕我的快速手指。幸运的是,我在离开该评论前2分钟对该帖子进行了编辑,以便它**具有正确的示例。对于那个很抱歉。 – Connell

+0

没问题,我删除了我的评论和+1。 – Rob

9

我相信你要找的是什么?

if ((row["LevelName"] as String) != "ABC") 

没有隐式转换DBNull和String之间。

它可能以前工作过,因为刚好在您的数据库中该列中没有NULL。也许有些数据被破坏,或者有人在表上改变了NOT NULL约束。

基本上,如果您明确施放了某些东西,最好确保它们具有兼容的动态类型,否则会抛出异常。 as操作员基本上说“如果可能的话将其转换为此值,否则逻辑值为空。”显然,as运算符只能用于引用类型,因为结构不能为空。

+2

你的答案暗示了这一点,但值得说明的是:在使用显式类型转换'(Type)变量'会导致'InvalidCastException'的情况下,使用'variable as Type'将产生'null'。 – Rob

2

.NET nullDBNull.Value之间存在差异。在这里,您可以看到类DBNull和该类的Value字段。

你应该能够做这样的事情:

if (row["LevelName"].Value == DBNull.Value) 
    return false; 
else if (row["LevelName"].ToString() != "ABC") 
    // do something 
    // .... 
3

DBNull表示数据库中的空值。这与.NET null不同,它表示一个空引用。

代码突然失败,因为有人更改或插入了空白的记录。

是的,字符串可以为空,但是您将一个dbnull投射到字符串。您必须检查dbnull,如果它存在,则将其替换为null。

4

DBNull表示在给定的数据库列中没有数据。如果在数据库中创建新记录,但没有将值分配给“LevelName”列,则会发生这种情况。

DBNull与空对象引用或空字符串变量不同。 DBNull表示列数据从未设置。如果您为“LevelName”列指定一个空值,那么该列已经初始化并且它将返回null(而不是DBNull)。