【问题标题】:What is the difference between null and System.DBNull.Value?null 和 System.DBNull.Value 有什么区别?
【发布时间】:2011-06-24 21:49:01
【问题描述】:

null 和 System.DBNull.Value 有什么区别吗?如果有,是什么?

我现在注意到了这种行为 -

while (rdr.Read())
{
    if (rdr["Id"] != null) //if (rdr["Id"] != System.DBNull.Value)  
    {
        int x = Convert.ToInt32(rdr["Id"]);
    }
}

虽然我使用 sql 数据读取器从数据库中检索数据,但没有返回值 if(rdr["Id"] != null) 返回 true 并最终引发了将 null 转换为整数的异常。

但是,如果我使用if (rdr["Id"] != System.DBNull.Value),这将返回false

null 和 System.DBNull.Value 有什么区别?

【问题讨论】:

  • 嗯,它们是无关的。一个是System.Data 中类的静态实例,另一个是表示缺少所指对象的特殊值。他们彼此没有任何关系。你能详细说明你对什么感到困惑吗?你真正的问题是“为什么DataRowsDataReadersDBNull.Value 放在自己内部而不是null?”
  • 嗯,我一开始不是这样,但在了解了你所说的之后,我很好奇。你能告诉我为什么 DataRows 和 DataReaders 把 DBNull.Value 放在自己里面而不是 null 吗?
  • 我自己也不确定。这是一个答案:stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull/… 也有可能在 C# 中出现可空值类型之前,处理null 会更加麻烦。
  • 我在这里有一个答案,但我意识到它更适合stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull - 所以我移动了它

标签: c# null dbnull


【解决方案1】:

嗯,null 不是任何类型的实例。相反,它是一个无效的引用。

但是,System.DbNull.Value 是对 System.DbNull 实例的有效引用(System.DbNull 是单例,System.DbNull.Value 为您提供对该类的单个实例的引用),它表示不存在* 数据库中的值。

*我们通常会说null,但我不想混淆这个问题。

因此,两者之间存在很大的概念差异。关键字null 表示无效引用。 System.DbNull 类表示数据库字段中不存在的值。一般来说,我们应该尽量避免使用相同的东西(在本例中为 null)来表示两个非常不同的概念(在本例中为无效引用与数据库字段中不存在的值)。

请记住,这就是为什么很多人通常提倡使用 null object pattern,这正是 System.DbNull 的一个例子。

【讨论】:

  • +1 一个实际的例子:如果您使用IDbCommand.ExecuteScalar(),它可以返回null(不返回任何记录)或DbNull(第一条记录中的第一列是“不存在的值”)。如果没有DbNull,您将无法区分两者。
  • 我强烈建议使用一种禁止使用 Null 的语言,这样做的额外费用绝对是 0。 “空对象模式”的生命太短了
  • 空引用是完全有效的。 ☺
  • @C.Evenhuis 好吧,还有另一个常见的建议:函数应该只返回一种类型的值。这就是为什么人们更喜欢类型良好的 TypeScript 代码。 “执行的状态是什么”不同于“计算结果是什么”。 IE。他们本可以决定以其他方式实现此功能(可能是一个输出参数,或类似于 HTTP 请求响应 objs 的对象)。当然,这不是真正想要的复杂情况,但如果他们这样做了,也许可以使用 null 代替 DbNull。
【解决方案2】:

来自DBNull class的文档:

不要将面向对象编程语言中的 null 概念与 DBNull 对象混淆。在面向对象的编程语言中,null 表示没有对对象的引用。 DBNull 表示未初始化的变体或不存在的数据库列。

【讨论】:

    【解决方案3】:

    DBNull.Value 处理起来很烦人。

    我使用静态方法检查它是否为 DBNull,然后返回值。

    SqlDataReader r = ...;
    String firstName = getString(r[COL_Firstname]);
    
    private static String getString(Object o) {
       if (o == DBNull.Value) return null;
       return (String) o;
    }
    

    另外,在向 DataRow 中插入值时,不能使用“null”,必须使用 DBNull.Value。

    有两个“null”表示是一个糟糕的设计,没有明显的好处。

    【讨论】:

    • 我们共同的厌恶情绪:你的最后一句话被讽刺的是,出现在这里阅读这篇文章并发现你的用户名是“厌恶”
    【解决方案4】:

    DBNull.Value 是 .NET 数据库提供程序返回以表示数据库中的空条目。 DBNull.Value 不为空,从数据库行检索的列值与空值的比较将不起作用,您应始终与 DBNull.Value 进行比较。

    http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx

    【讨论】:

    • 附注还应该使用 DBNull.Value 将空参数传递给数据库,否则可能会被解释为未传递参数。
    • DBNull 不是“数据库返回的内容”——这只是 ADO.NET 选择解释它的方式;我个人不确定这种解释是否非常有价值
    • @MarcGravell 是的,马克,你是对的。我措辞不正确。 ASP.NET 将数据库空列值转换为 DBNull.Value
    【解决方案5】:

    DataRow 有一个名为 IsNull() 的方法,您可以使用该方法测试列是否为空值 - 与数据库看到的空值有关。

    DataRow["col"]==null 将始终为 false

    使用

    DataRow r;
    if (r.IsNull("col")) ...
    

    改为。

    【讨论】:

      【解决方案6】:

      Null 类似于 C++ 中的零指针。所以它是一个不指向任何值的引用

      DBNull.Value完全不同,是一个常量,当字段值包含NULL时返回。

      【讨论】:

        猜你喜欢
        • 2011-02-14
        • 1970-01-01
        • 2011-04-16
        • 2016-12-23
        • 1970-01-01
        • 2017-04-02
        • 1970-01-01
        相关资源
        最近更新 更多