In this SO post I found a generic extension method which returns a default value if a value read by an SqlDataReader
is null
or DBNull.Value
, and the correctly converted value otherwise. I implemented it like this:
public static T GetValueOrDefault<T>(this SqlDataReader reader, string columnName, T defaultValue = default(T))
{
object val = reader[columnName];
if (val == null || val == DBNull.Value)
{
return defaultValue;
}
return (T)val;
}
The examples mentioned below the method in the post linked above don't use the correct syntax, but nevertheless suggest that this should also work with nullable types such as int?
.
However, I read a nullable int
column from the database like this:
MyProperty = reader.GetValueOrDefault<int?>("SomeColumnName")
where debug mode shows me that val
is -1
and T
is int?
, but I get an InvalidCastException. From this post I figured it's because unboxing and casting can't be performed in a single operation (val
is of type object
holding a short
value), but what can I do to make it work in my case? Since it's a generic method, I wouldn't know how to manually unbox it before doing the conversion.
For a really good answer, you need to post a good, minimal, complete code example.
If a cast to int
fails, then the boxed value isn't an int
. You should be able to see in the debugger what it actually is.
That said, the Convert
class is a lot more sophisticated about conversions; the cast will require an exact match, i.e. the boxed value must be an int
(the literal -1
would be an int
, but in your case the value's coming from who-knows-where and easily could be a short
or long
or whatever).
So instead of the cast, a call e.g. to Convert.ToInt32()
would work better.
In your case, with the generic method (i.e. the type is unknown at compile-time), the Convert.ChangeType()
method is probably more appropriate:
public static T GetValueOrDefault<T>(this SqlDataReader reader, string columnName, T defaultValue = default(T))
{
object val = reader[columnName];
if (val == null || val == DBNull.Value)
{
return defaultValue;
}
return (T)Convert.ChangeType(val, typeof(T));
}