对空字符串和DBNull感到困惑

时间:2011-11-07 23:03:38

标签: .net sql string null dbnull

我正在查看我正在研究的.net程序的一些代码。该程序的前一位作者在一年多前向我提供了代码。突然间,我看到代码抛出了一个我没有触及的异常:

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

异常是“无法将'System.DBNull'类型的对象强制转换为'System.String'。

我认为该字符串是可以为空的数据类型,所以我怎么可能得到这个例外?

5 个答案:

答案 0 :(得分:9)

我相信你所寻找的是:

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

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

之前可能有用,因为数据库中该列恰好没有NULL。可能有些数据已损坏,或有人在表上更改了NOT NULL约束。

基本上,如果您明确地投射某些东西,最好确保它们具有兼容的动态类型,否则会抛出异常。 as运算符基本上表示“如果可能,将其强制转换为此值,否则逻辑值为空”。显然,as运算符仅适用于引用类型,因为结构不能为null。

答案 1 :(得分:7)

DBNull是它自己的类,它在名为singleton的属性中包含自己的Value个实例。 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子句中,我发现这非常方便,只是一个简单的实例。

答案 2 :(得分:4)

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

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

答案 3 :(得分:3)

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

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

是的,字符串可以为空,但是你将dbnull强制转换为字符串。你必须检查dbnull,如果它在那里就用null替换它。

答案 4 :(得分:2)

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

你应该可以这样做:

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