我正在查看我正在开发的 .net 程序的一些代码。该程序的前任作者在一年前将代码提供给了我。突然,我看到一个我没有接触过的代码抛出的异常:
if ((string)row["LevelName"] != "ABC")
例外是“无法将 'System.DBNull' 类型的对象转换为 'System.String' 类型。
我认为该字符串是可以为空的数据类型,那么我怎么可能得到这个异常呢?
我相信您正在寻找的是:
if ((row["LevelName"] as String) != "ABC")
DBNull 和 String 之间没有隐式转换。
它以前可能有效,因为恰好在您的数据库中的该列中没有空值。也许某些数据已损坏,或者有人更改了表上的 NOT NULL 约束。
基本上,如果你显式地强制转换某些东西,你最好确保它们具有兼容的动态类型,否则会引发异常。运算符基本上说“如果可能,将as
其转换为 this,否则逻辑值为 null。” 显然,as
运算符仅适用于引用类型,因为结构不能为空。
DBNull是它自己的类,它在一个名为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 选择子句中的一个以防万一的场景,我发现这非常方便。
DBNull 表示给定的数据库列中没有数据。如果在数据库中创建了新记录但没有为“LevelName”列分配值,则可能会发生这种情况。
DBNull 与空对象引用或空字符串变量不同。DBNull 表示从未设置过列数据。如果将 null 分配给“LevelName”列,则该列已被初始化,它将返回 null(不是 DBNull)。
DBNull 表示数据库中的空值。这与 .NET null 不同,后者表示空引用。
代码突然失败,因为有人更改或插入了一条包含空值的记录。
是的,字符串可以为空,但是您将 dbnull 转换为字符串。您必须检查 dbnull,如果存在则将其替换为 null。
null
.NET和.NET 之间存在差异DBNull.Value
。在这里,您可以看到DBNull
类是什么以及该类的Value字段。
你应该能够做这样的事情:
if (row["LevelName"].Value == DBNull.Value)
return false;
else if (row["LevelName"].ToString() != "ABC")
// do something
// ....