【问题标题】:Confused about null strings and DBNull对空字符串和 DBNull 感到困惑
【发布时间】:2011-11-07 23:03:38
【问题描述】:

我正在查看我正在开发的 .net 程序的一些代码。该程序的前任作者在一年前将代码提供给了我。突然,我看到一个我没有接触过的代码抛出的异常:

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

例外是“无法将'System.DBNull'类型的对象转换为'System.String'类型。

我认为字符串是可以为空的数据类型,那么我怎么可能得到这个异常呢?

【问题讨论】:

  • 这段代码已经运行了一年多;我觉得我一定是在什么地方搞砸了
  • 是的,事实上,我做到了。有问题的代码没有为 DBNull 值准备,因为它不应该出现在我正在运行的特定查询中。我在修改查询时犯了一个错误,因此出现了错误。
  • 感谢大家提供的信息丰富的答案。我对他们都投了赞成票。难怪我读的 SQL 书把 NULL 称为“那个四个字母的单词”。

标签: .net sql string null dbnull


【解决方案1】:

我相信您正在寻找的是:

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

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

它以前可能工作过,因为您的数据库中的该列中恰好没有 NULL。可能某些数据已损坏,或者有人更改了表上的 NOT NULL 约束。

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

【讨论】:

  • 您的回答暗示了这一点,但值得说明的是:使用 variable as Type 将产生 null 在使用显式转换 (Type) variable 会导致 InvalidCastException 的情况下。
【解决方案2】:

DBNull 是它自己的类,它在一个名为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 选择子句中的一个以防万一的场景。

【讨论】:

  • 恐怕我的手指很快。幸运的是,我在您离开该评论前 2 分钟编辑了该帖子,以便它确实有一个正确的示例。对此感到抱歉。
  • 没问题,我删除了我的评论并 +1。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

    是的,字符串可以为空,但是您将 dbnull 强制转换为字符串。您必须检查 dbnull,如果存在则将其替换为 null。

    【讨论】:

      【解决方案5】:

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

      你应该可以做这样的事情:

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

      【讨论】:

        猜你喜欢
        • 2015-03-13
        • 1970-01-01
        • 1970-01-01
        • 2017-10-19
        • 1970-01-01
        • 2020-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多