Is there any smart way to abbreviate this obscenity? It works, but it's unreadable...
int? myVal = r.IsDBNull(r.GetOrdinal("colName")) ? (int?)null : r.GetInt32(r.GetOrdinal("colName"));
Thanks :)
You could put that code into an extension method on the DbDataReader (or even better on the IDataReader interface that it implements). That way, the horrible-looking code is hidden away behind a nicer looking GetNullableInt32() call:
public static class IDataReaderExtensions
{
public static int? GetNullableInt32(this IDataReader r, string columnName)
{
int? myVal = r.IsDBNull(r.GetOrdinal(columnName))
? (int?) null :
r.GetInt32(r.GetOrdinal(columnName));
return myVal;
}
}
You can then call it using:
IDataReader reader = ...;
int? value = reader.GetNullableInt32("colName");
As Ian points out, it would be better to call r.GetOrdinal() just the once:
public static class IDataReaderExtensions
{
public static int? GetNullableInt32(this IDataReader r, string columnName)
{
int ordinal = r.GetOrdinal(columnName);
int? myVal = r.IsDBNull(ordinal)
? (int?) null :
r.GetInt32(ordinal);
return myVal;
}
}
Further to Adrian's answer, you could make a generic extension method to cater for all types:
int? myVal = r.GetValue<int?>("colName");
// ...
public static class DataReaderExtensions
{
public static T GetValue<T>(this IDataReader dr, string columnName)
{
return dr.GetValue<T>(dr.GetOrdinal(columnName));
}
public static T GetValue<T>(this IDataReader dr, int columnOrdinal)
{
// does the column contain null?
if (dr.IsDBNull(columnOrdinal))
{
// is T either a ref type or a nullable value type?
Type t = typeof(T);
if (!t.IsValueType || (Nullable.GetUnderlyingType(t) != null))
{
// return null
return default(T);
}
}
// get the column value, cast it as T and return it
// this will throw if the value isn't convertible/unboxable to T
return (T)dr.GetValue(columnOrdinal);
}
}
GetNullableInt32()call.default(int?)instead of(int?)null. Maybe it's not a great improvement, but casting null just to get the compiler to parse the type bugs me.