C# 数据库访问:DBNull 与 null

Posted

技术标签:

【中文标题】C# 数据库访问:DBNull 与 null【英文标题】:C# Database Access: DBNull vs null 【发布时间】:2010-09-05 23:37:51 【问题描述】:

我们在这里使用自己的 ORM,并为我们所有的数据库表提供强类型包装器。我们还允许执行弱类型的 ad-hoc SQL,但这些查询仍然通过同一个类从数据读取器中获取值。

在调整该类以使用 Oracle 时,我们遇到了一个有趣的问题。使用 DBNull.Value 还是 null 更好?使用 DBNull.Value 有什么好处吗?使用 null 似乎更“正确”,因为我们已经将自己与 DB 世界分开了,但是有一些影响(例如,当值为 null 时,你不能盲目地 ToString())所以它绝对是我们需要的做出有意识的决定。

【问题讨论】:

【参考方案1】:

我发现使用 null 比使用 DB null 更好。

原因是,正如您所说,您将自己与 DB 世界分开。

检查引用类型以确保它们不为空通常是一种很好的做法。您将检查数据库数据以外的内容是否为 null,我发现最好在整个系统中保持一致性,并使用 null,而不是 DBNull

从长远来看,在架构上我发现它是更好的解决方案。

【讨论】:

【参考方案2】:

如果您已经编写了自己的 ORM,那么我会说只使用 null,因为您可以随心所欲地使用它。我相信 DBNull 最初只是用来解决值类型(int、DateTime 等)不能 null 的事实,而不是返回一些像零或 DateTime.Min 这样的值,这将暗示一个空值(坏的,坏的),他们创建了 DBNull 来表明这一点。也许还有更多,但我一直认为这就是原因。但是,现在我们在 C# 3.0 中有了可为空的类型,不再需要 DBNull。事实上,LINQ to SQL 只是到处使用 null。完全没有问题。拥抱未来...使用null。 ;-)

【讨论】:

我觉得DBNull还是有一些用途的。至少使用 sqlite,我可以测试 ExecuteScalar() 返回的值是否显式存储在数据库中。考虑表 foo(a int, b int);单行(1,空)。如果我们要在命令“SELECT b FROM foo WHERE A = 1”上执行Scalar,它将返回 DBNull.Value(存在的行存储了一个空值)。如果我在“SELECT b FROM foo WHERE A = 2”上调用 ExecuteScalar,它将返回 null(不存在这样的行)。据推测,您可以使用 DataReader 获得相同的结果,但我很欣赏它的便利性。 有趣。在使用 ORM 进行数据库访问时,我通常不会在我的代码中明确使用 ExecuteScalar。我通常最终检索完整的实体对象并以这种方式查看它们的值。因此,如果实体本身为 null,那是一回事,如果值为 null,那又是另一回事。只是做法不同而已。我承认如果你只需要一个值,ExecuteScalar 会更有效。【参考方案3】:

根据我的经验,.NET DataTables 和 TableAdapters 与 DBNull 配合得更好。它还在强类型时打开了一些特殊方法,例如 DataRow.IsFirstNameNull 到位时。

我希望我能给你一个比这更好的技术答案,但对我来说,底线是在处理与数据库相关的对象时使用 DBNull,然后在处理对象和 .NET 时使用“标准”null相关代码。

【讨论】:

【参考方案4】:

使用DBNull。 我们在使用 null 时遇到了一些问题。 如果我没记错的话,您不能在字段中插入空值,只能插入 DBNull。 可能只是Oracle相关的,对不起,我不知道细节了。

【讨论】:

以上是关于C# 数据库访问:DBNull 与 null的主要内容,如果未能解决你的问题,请参考以下文章

null 和System.DBNull.Value

DBNull和Null的区别

如何将 collasce null 运算符与 DbNull.Value 一起使用?

[C#] 如何优雅的解决 DBNull 问题

[C#] 如何优雅的解决 DBNull 问题

如果数据为null,则转成数据库可识别的DBNULL.Value