简体   繁体   中英

What in the DBNull

I have a stored procedure which has a parameter that is nullable to a decimal column. The method I wrote expects a Dictionary<string, string> to pass the parameter name and the value.

However, when I use reflection to GetValue when I do:

collection.Add(model.Name, DBNull.Value.ToString());

In essence all DBNull.Value returns would be a String.Empty . So how can I ensure the null is correctly passed to SQL Server? Otherwise that will throw an exception, because invalid column data type. The documentation states, with ToString it will return String.Empty .

DBNull is a singleton class, which means only this instance of this class can exist. If a database field has missing data, you can use the DBNull.Value property to explicitly assign a DBNull object value to the field. However, most data providers do this automatically. To evaluate database fields to determine whether their values are DBNull, you can pass the field value to the DBNull.Value.Equals method. However, this method is rarely used because there are a number of other ways to evaluate a database field for missing data. These include the Visual Basic IsDBNull function, the Convert.IsDBNull method, the DataTableReader.IsDBNull method, the IDataRecord.IsDBNull method, and several other methods.

This would be added to the database in the following manner:

command.Parameters.AddWithValue(parameter.Key, parameter.Value);

A traditional Ado.Net SqlDataReader .

I think you will have to get each value from the Dictionary and then use code like that shown below before passing the parameter to the command. In other words, store null as the value in the Dictionary, not DBNull, then call the code below to convert from null to DBNull.Value.

        SqlParameter firstNameParam = new SqlParameter("FirstName", System.Data.SqlDbType.NVarChar);
        string firstNameValue = null; // this is the value from the Dictionary
        if (firstNameValue == null) {
            firstNameParam.Value = DBNull.Value;
        }
        else {
            firstNameParam.Value = firstNameValue;
        }

After refactoring, you could do something like this:

  public static object ToDBNull(object value) {
        if (value == null) {
            return DBNull.Value;
        }
        else {
            return value;
        }
    }

Then call ToDBNull function like this:

        cmd.Parameters.AddWithValue("FirstName", ToDBNull(firstNameValue));

If you have Dictionary<string, string> , and you have a value in the dictionary such that:

var dictionary = new Dictionary<string, string>() { { "hello", null } };

string data = dictionary["hello"];
var dec = data == null ? (decimal?)null : Convert.ToDecimal(data);

You could write a little extension method to make things easier for passing it to a command

public static object ValueOrDbNull(this decimal? value)
{
    if (value.HasValue)
    {
        return value;
    }

    return DBNull.Value;
}

And then add it to your command as such:

command.Parameters.Add("@your_proc_param", dec.ValueOrDbNull());

There shouldn't be any issues passing it to a procedure in this manner, since you said it's declared as a nullable decimal field.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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