繁体   English   中英

是否可以在C#中合并字符串和DBNull?

[英]Is it possible to coalesce string and DBNull in C#?

我正在编写一个C#例程来调用存储过程。 在我传入的参数列表中,其中一个值可能合法地为空。 所以我以为我会使用这样的一行:

cmd.Parameters.Add(new SqlParameter("@theParam", theParam ?? DBNull.Value));

不幸的是,这会返回以下错误:

CS0019:运营商'??' 不能应用于'string'和'System.DBNull'类型的操作数

现在,这似乎已经足够清楚,但我不明白其背后的基本原理。 为什么这不起作用? (通常情况下,当我不明白为什么某些东西不能正常工作时,并不是它无法正常工作......而是我做错了。)

我是否真的需要将其延伸到更长的if-then声明中?

编辑:(顺便说一句,对那些建议只使用“null”的人,它不起作用。我原来认为null也会自动翻译成DBNull,但它显然没有。(谁知道?))

不是那样的,没有。 类型必须匹配。 三元组也是如此。

现在,通过“匹配”,我并不是说他们必须是一样的。 但它们必须兼容分配。 基本上:在同一个继承树中。

解决此问题的一种方法是将字符串转换为对象:

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; 
}

另请注意,我明确声明了参数类型。

new SqlParameter("@theParam", (object)theParam ?? DBNull.Value)

?? ?? 如果左侧操作数不为null,则运算符返回左侧操作数,否则返回右侧操作数。 但在你的情况下,它们是不同的类型,所以它不起作用。

您不能使用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)
);

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))

在你声明传入变量的存储过程中,让它将var设置为null然后不从csharp代码中传入它,然后它将从sql中获取默认值

@theParam as varchar(50) = null

然后在你的csharp中

if (theParam != null)
    cmd.Parameters.Add(new SqlParameter("@theParam", theParam));

这就是我通常将选项和/或默认值传递给我的存储过程

我很确定只是将null传递给SqlParameter构造函数会导致它作为DBNull.Value发送...我可能会弄错,因为我使用EnterpriseLibraries进行数据库访问,但我很确定发送一个null在那里很好。

cmd.Parameters.Add(new SqlParameter(“@ theParam”,(theParam == null)?DBNull.Value:theParam));

使用以下语法:

(theParam作为对象)?? (DBNull.Value作为对象)

在这种情况下,操作员的两个部分?? 属于同一类型。

不确定你问题的具体答案,但是这个怎么样?

string.IsNullOrEmpty(theParam) ? DBNull.Value : theParam

或者如果空白就可以了

(theParam == null) ? DBNull.Value : theParam

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM