C#/Oracle10g = null vs DBNull.Value vs String.Empty C#和Oracle10g中的null、DBNull.Value和String.Empty的区别。

5
我正在初步学习如何从C#访问Oracle。我发现Oracle不支持将VarChar参数的值设为null(C#)。我本以为会有一些隐式转换,但我理解其中的差异。
因此,我需要捕获这些空值并提供DBNull.Value,是吗?最明显的方法是使用合并运算符??
param myParm = myObject.MyProperty ?? DBNull.Value;

但是它不接受 System.DBNull 的值,所以我必须使用:

param myParm = myObject.MyProperty ?? DBNull.Value.ToString();

...这与以下内容相同:

param myParm = myObject.MyProperty ?? String.Empty;

...同样有效。

但是我一直认为根据ANSI SQL规则,空字符串("") != NULL值......然而在Oracle中似乎是这样的。

无论如何,我的问题是,处理空字符串值的情况最好、实用或理论上的方法是什么?是否有我尚未确定的巧妙替代方案?还是这只是我们接受的Oracle的另一个怪癖?

3个回答

4
一个空字符串("")并不等于NULL值,这是因为NULL不等于任何东西(甚至不等于另一个NULL),这也是为什么在SQL语句中使用IS NULL而不是= NULL的原因。
NULL表示“没有值”,而一个空字符串没有值,所以Oracle的设计者认为空字符串和NULL没有区别。 param myParm = myObject.MyProperty ?? DBNull.Value;失败是因为??两边必须是相同的类型。MyProperty我假设是一个字符串,而DBNull.Value是一个DBNull对象。

1
我很感谢你的回答,James。但是你只是在重复我的学习过程... 但是在我看来,从C# null推断出DB NULL比从空字符串推断出DB NULL更有意义。尽管如此,我有两个替代方案;问题是哪一个更好(这有关系吗?)并且是否有其他选择。 - CJM
嗯...听起来有点批评,但我并不是这个意思。我只是想表达当时我的思路,并且意识到String!= System.DBNull。 - CJM

1

这里有一个更简单的解决方案,因为 ?? 不能工作,而 String.Empty 也不能用于您的null值。

param myParm;

if (myObject.MyProperty == null)
{
   myParm  = DBNull.Value;
}
else 
{
   myParm = myObject.MyProperty;
}

它可能没有空值合并运算符那么“流畅”,但它应该能够工作。


我不能说我已经彻底测试过它(尽管我在测试时很疲惫!),但是String.Empty似乎可以工作。不过,我不确定它是否应该这样。 - CJM
String.Empty可以工作,因为.NET将空字符串作为值传递,而Oracle将空字符串视为NULL。也就是说,在SQL Server中,“'' IS NULL”为假,但在Oracle中为真。 - stevemegson
@stevemegson 和 @CJM,我错过了你们问题中提到的 String.Empty 也可以使用这一行代码,这使得我对你们问题的理解产生了困惑。 - msarchet

1

如果您将值设置为null,.NET在生成的SQL中将不指定该参数。因此,在Oracle中为参数指定默认值NULL是一种选择。这意味着将值设置为nullDBNull.Value具有相同的效果。一个传递没有值,将假定为NULL,而另一个明确地传递了一个NULL值。

显然,这假设您可以修改数据库,并且您不需要为该参数使用不同的默认值。


我的同事控制着数据库,所以这同样是可能的,谢谢。 - CJM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接