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

心不动则不痛 提交于 2019-11-30 12:44:05

Not like that, no. The types have to match. The same is true for the ternary.

Now, by "match", I don't mean they have to be the same. But they do have to be assignment compatible. Basically: in the same inheritance tree.

One way to get around this is to cast your string to object:

var result = (object)stringVar ?? DBNull.Value;

But I don't like this, because it means you're relying more on the SqlParameter constructor to get your types right. Instead, I like to do it like this:

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

Note also that I explicitly declared the parameter type.

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

The ?? operator returns the left-hand operand if it is not null, or else it returns the right operand. But in your case they are different types, so it doesn't work.

The Null Coalesce operator only with with data of the same type. You cannot send NULL to the SqlParamater as this will make Sql Server says that you didn't specify the parameter.

You can use

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

Or you could create a function that return DBNull when null is found, like

public static object GetDataValue(object o)
{
    if (o == null || String.Empty.Equals(o))
        return DBNull.Value;
    else
        return o;
}

And then call

new SqlParameter("@theParam", GetDataValue(theParam))

The reason you can't use the null coalesce operator is that it has to return one type and you are providing more than one type. theParam is a string. DbNull.Value is a reference to a static instance of type System.DbNull. This is what its implementation looks like;

public static readonly DBNull Value = new DBNull(); 
//the instantiation is actually in the 
//static constructor but that isn't important for this example

So if you were to have a NullCoalesce method, what would its return type be? It can't be both System.String and System.DbNull, it has to be one or the other, or a common parent type.

So that leads to this type of code;

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

In your stored proc when you declare the incoming variable, have it set the var equal to null and then do not pass it in from your csharp code, it will then pick up the default value from sql

@theParam as varchar(50) = null

and then in your csharp

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

This is how I usually pass option and/or defaulted values to my stored procs

I'm pretty sure that just passing a null to the SqlParameter constructor results in it being sent as a DBNull.Value... I may be mistaken, since I use the EnterpriseLibraries for DB access, but I'm quite sure that sending a null is fine there.

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

Use this syntax:

(theParam as object) ?? (DBNull.Value as object)

In this case both parts of operator ?? are of the same type.

Not sure the specific answer to your question, but how about this?

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

or if blank is ok

(theParam == null) ? DBNull.Value : theParam
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!