我正在查看我正在研究的.net程序的一些代码。该程序的前一位作者在一年多前向我提供了代码。突然间,我看到代码抛出了一个我没有触及的异常:
if ((string)row["LevelName"] != "ABC")
异常是“无法将'System.DBNull'类型的对象强制转换为'System.String'。
我认为该字符串是可以为空的数据类型,所以我怎么可能得到这个例外?
答案 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 null
和DBNull.Value
之间存在差异。在这里,您可以看到DBNull
类是什么以及该类的Value字段。
你应该可以这样做:
if (row["LevelName"].Value == DBNull.Value)
return false;
else if (row["LevelName"].ToString() != "ABC")
// do something
// ....