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


91

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

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

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

虽然我使用sql datareader从数据库检索数据,但是没有返回if(rdr["Id"] != null)返回的值true,最终抛出了将null强制转换为整数的异常。

但是,如果我使用if (rdr["Id"] != System.DBNull.Value)return的话false

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


好吧,它们是无关的。一个是中的类的静态实例,System.Data另一个是表示缺少引用对象的特殊值。他们彼此无关。您能详细说明一下您困惑的地方吗?是您真正的问题“为什么DataRowsDataReadersDBNull.Value里面本身,而不是null?”
mqp 2011年

好吧,我最初不是,但是从您的发言中吸取教训后,我很好奇。您能告诉我为什么DataRows和DataReaders将DBNull.Value放在自己而不是null中吗?
2011年

我不确定自己。这是一个答案:stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull / ...在C#中出现空值类型之前,也可能会比较麻烦null
mqp 2011年

1
我在这里有一个答案,但我意识到它更适合stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull-因此我将其移了
Marc Gravell

Answers:


115

好吧,null不是任何类型的实例。而是,它是无效的引用。

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

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

因此,两者之间存在很大的概念差异。关键字null代表无效的参考。该类System.DbNull表示数据库字段中不存在的值。通常,我们应该尝试避免使用同一事物(在这种情况下null)来表示两个截然不同的概念(在这种情况下,无效引用与数据库字段中不存在的值)。

请记住,这就是为什么许多人通常都提倡使用空对象模式的原因,这正是System.DbNull一个例子。


43
+1一个实际示例:如果使用IDbCommand.ExecuteScalar(),则它可以返回null(不返回记录)或DbNull(第一条记录中的第一列是“不存在的值”)。没有DbNull您,您将无法将彼此区分开。
C.Evenhuis

我强烈建议您使用一种禁止使用Null的语言,并且绝对要额外支付0。生命对于“空对象模式”而言太短了
nicolas 2014年

3
空引用是完全有效的。☺
IllidanS4希望莫妮卡回

@ C.Evenhuis好吧,还有另一种常见建议:函数应仅返回一种类型的值。这就是为什么人们偏爱类型正确的TypeScript代码。“执行状态是什么”与“计算结果是什么”不同。就是 他们可能已经决定以其他方式实现此功能(可能是out参数,或者类似于HTTP请求响应objs的对象)。当然,这不是真正想要的并发症,但是如果他们这样做了,也许可以使用null代替DbNull。
klenium

21

DBNull类的文档中:

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


11

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”是一个不好的设计,没有明显的好处。


2
我们共同的厌恶情绪是:您的最后一句话仅因讽刺而被打败,因为讽刺的是,出现在这里以阅读本文并发现您的用户名“
讨厌

5

.NET数据库提供程序返回的DBNull.Value代表数据库中的空条目。DBNull.Value不为null,并且从数据库行检索的列值的比较结果为null无效,您应该始终将其与DBNull.Value进行比较。

http://msdn.microsoft.com/zh-CN/library/system.dbnull.value.aspx


ps您还应该使用DBNull.Value将空参数传递给数据库,否则它可能被解释为未传递参数。
詹姆斯·迈克尔·哈尔

1
DBNull 不是 “数据库返回的内容”,而是ADO.NET选择解释它的方式。我个人不确定这种解释是否很有价值
Marc Gravell

@MarcGravell是的,Marc,您是对的。我说错了。ASP.NET将数据库的空列值转换为DBNull.Value
James Michael Hare

3

DataRow有一个被调用的方法,IsNull()如果该列具有null值,则可以用来测试该列-与数据库所看到的null有关。

DataRow["col"]==null永远是false

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

代替。


3

空值类似于C ++中的零指针。因此,它是不指向任何值参考

DBNull.Value是完全不同的,并且是一个常量,当字段值包含NULL时将返回该常量

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.