Creating null value SqlParameter parameter objects with AddWithValue






4.90/5 (3 votes)
On problems that arise tying to add a null valued SqlParameter using the SqlParameterCollection.AddWithValue method.
I'm sure you are all familiar with code such as the following, to easily convert a bunch of parameter values stored in good old .NET object properties:
using (var sqn = new SqlConnection(ConfigurationManager.ConnectionStrings["ReportStaging"].ConnectionString)) {
using (var cmd = new SqlCommand(sql, sqn)) {
sqn.Open();
cmd.Parameters.AddWithValue("@Category", line.Category);
cmd.Parameters.AddWithValue("@DailyActual", line.DailyActual);
cmd.Parameters.AddWithValue("@DailyPlan", line.DailyPlan);
cmd.ExecuteNonQuery();
}
}
A problem arises when a property such as line.DailyActual
is set to null
. Our friend, the SqlParameterCollection.AddWithValue
method inconveniently ignores the well known fact that the .NET null
value and the SqlClient DBNull
value are worlds apart. Instead of AddWithValue
adding a parameter with the value of DBNull.Value
when it encounters a null
reference for its value
parameter, it simply doesn't add a parameter at all, exposing the suggestion of convenience in its name as a dirty, stinking lie.
Only when the code above reaches the cmd.ExecuteNonQuery()
call is the brain death of AddWithValue
exposed, by an exception of type SqlException
, bearing the message:
Most workarounds for this scenario involve convoluted ternary operator voodoo or excessively verboseQuote:The [parameterized query] expects the parameter '@DailyActual', which was not supplied.
if
statements, but we can cleanly and easily apply .NET's wonderful extension methods in cases like this. In the following class and extension method, I add an overload to AddWithValue
that takes a third parameter, nullValue
that specifies what value to create a parameter with if the actual parameter value is null
:
public static class SqlParameterCollectionExtensions {
public static SqlParameter AddWithValue(this SqlParameterCollection target, string parameterName, object value, object nullValue) {
if (value == null) {
return target.AddWithValue(parameterName, nullValue ?? DBNull.Value);
}
return target.AddWithValue(parameterName, value);
}
}
Now we insist that our method is called instead of the dodgy Microsoft one, by supplying the third parameter, like this, and it adds all required parameters, with DBNull.Value
values when we want to pass null
s:
cmd.Parameters.AddWithValue("@Category", line.Category);
cmd.Parameters.AddWithValue("@DailyActual", line.DailyActual, null);
cmd.Parameters.AddWithValue("@DailyPlan", line.DailyPlan, null);
This is a quick after supper scrawl and by no means a lofty exegisis on this topic. Please feel free to correct me or make suggestions.