The parameterized query ..... expects the parameter '@units', which was not supplied
Try this code:
SqlParameter unitsParam = command.Parameters.AddWithValue("@units", units);
if (units == null)
{
unitsParam.Value = DBNull.Value;
}
And you must check all other parameters for null value. If it null you must pass DBNull.Value
value.
Here's a way using the null-coalescing operator:
cmd.Parameters.AddWithValue("@units", units ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@range", range ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@scale", scale ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@description", description ?? (object)DBNull.Value);
Or for more strict type checking:
cmd.Parameters.Add("@units", SqlDbType.Int).Value = units ?? (object)DBNull.Value;
cmd.Parameters.Add("@range", SqlDbType.Int).Value = range ?? (object)DBNull.Value;
cmd.Parameters.Add("@scale", SqlDbType.Int).Value = scale ?? (object)DBNull.Value;
cmd.Parameters.Add("@description", SqlDbType.VarChar).Value = description ?? (object)DBNull.Value;
The operator also be chained:
int?[] a = { null, null, 1 };
Console.WriteLine(a[0] ?? a[1] ?? a[2]);
This extension class was useful to me a couple of times so far, for those issues:
public static class DbValueExtensions
{
// Used to convert values coming from the db
public static T As<T>(this object source)
{
return source == null || source == DBNull.Value
? default(T)
: (T)source;
}
// Used to convert values going to the db
public static object AsDbValue(this object source)
{
return source ?? DBNull.Value;
}
}
You would normally use it in two scenarios. First, when creating parameters for your query:
var parameters = new Dictionary<string, object>
{
{ "@username", username.AsDbValue() },
{ "@password", password.AsDbValue() },
{ "@birthDate", birthDate.AsDbValue() },
};
or when parsing the SqlReader values:
while (reader.Read())
{
yield return new UserInfo(
reader["username"].As<string>(),
reader["birthDate"].As<DateTime>(),
reader["graduationDate"].As<DateTime?>(),
reader["nickname"].As<string>()
);
}