我正在编写一个C#例程来调用存储过程。在我传入的参数列表中,其中一个值可能合法地为空。所以我以为我会使用这样的一行:
cmd.Parameters.Add(new SqlParameter("@theParam", theParam ?? DBNull.Value));
不幸的是,这会返回以下错误:
CS0019:运营商'??'不能应用于'string'和'System.DBNull'类型的操作数
现在,这似乎已经足够清楚,但我不明白其背后的基本原理。为什么这不起作用? (而且,当我不明白为什么某些东西不起作用时,并不是不能工作......这就是我做错了。)
我是否真的必须将其延伸到更长的if-then声明中?
编辑:(顺便说一下,对于那些建议只使用“null”的人来说,它不起作用。我原来认为null也会自动翻译成DBNull,但显然不知道。(谁知道?))
答案 0 :(得分:16)
不是那样,不。类型必须匹配。三元也是如此。
现在,通过“匹配”,我并不是说他们必须是一样的。但它们必须兼容分配。基本上:在同一个继承树中。
解决此问题的一种方法是将字符串转换为object:
var result = (object)stringVar ?? DBNull.Value;
但我不喜欢这个,因为这意味着你更依赖于SqlParameter构造函数来使你的类型正确。相反,我喜欢这样做:
cmd.Parameters.Add("@theParam", SqlDbTypes.VarChar, 50).Value = theParam;
// ... assign other parameters as well, don't worry about nulls yet
// all parameters assigned: check for any nulls
foreach (var p in cmd.Parameters)
{
if (p.Value == null) p.Value = DBNull.Value;
}
另请注意,我明确声明了参数类型。
答案 1 :(得分:5)
new SqlParameter("@theParam", (object)theParam ?? DBNull.Value)
答案 2 :(得分:3)
??如果左侧操作数不为null,则运算符返回左侧操作数,否则返回右侧操作数。但在你的情况下,它们是不同的类型,所以它不起作用。
答案 3 :(得分:2)
您无法使用null coalesce运算符的原因是它必须返回一种类型,并且您提供了多种类型。 theParam
是一个字符串。 DbNull.Value
是对System.DbNull类型的静态实例的引用。这就是它的实现方式;
public static readonly DBNull Value = new DBNull();
//the instantiation is actually in the
//static constructor but that isn't important for this example
所以如果你有一个NullCoalesce方法,它的返回类型是什么?它不能是System.String和System.DbNull,它必须是一个或另一个,或者是一个共同的父类型。
因此导致这种类型的代码;
cmd.Parameters.Add(
new SqlParameter("@theParam", (object)theParam ?? (object)DBNull.Value)
);
答案 4 :(得分:2)
Null Coalesce运算符仅包含相同类型的数据。你不能向SqlParamater发送NULL,因为这会使Sql Server说你没有指定参数。
您可以使用
new SqlParameter("@theParam", (object)theParam ?? (object)DBNull.Value)
或者你可以创建一个在找到null时返回DBNull的函数,比如
public static object GetDataValue(object o)
{
if (o == null || String.Empty.Equals(o))
return DBNull.Value;
else
return o;
}
然后致电
new SqlParameter("@theParam", GetDataValue(theParam))
答案 5 :(得分:1)
在声明传入变量的存储过程中,让它将var设置为null,然后不将其从csharp代码中传入,它将从sql中获取默认值
@theParam as varchar(50) = null
然后在你的csharp
中if (theParam != null)
cmd.Parameters.Add(new SqlParameter("@theParam", theParam));
这就是我通常将选项和/或默认值传递给我的存储过程
的方法答案 6 :(得分:0)
我很确定只是将null传递给SqlParameter构造函数导致它作为DBNull.Value发送...我可能会弄错,因为我使用EnterpriseLibraries进行数据库访问,但我很确定那里发送一个空的很好。
答案 7 :(得分:0)
cmd.Parameters.Add(new SqlParameter(“@ theParam”,(theParam == null)?DBNull.Value:theParam));
答案 8 :(得分:0)
使用以下语法:
(theParam as object)?? (DBNull.Value作为对象)
在这种情况下,操作员的两个部分??属于同一类型。
答案 9 :(得分:-1)
不确定问题的具体答案,但是这个怎么样?
string.IsNullOrEmpty(theParam) ? DBNull.Value : theParam
或如果空白可以
(theParam == null) ? DBNull.Value : theParam