We have a collection of extension methods that can either handle this generically for all column types, or extensions for specific types, which makes the code read like the original set of DataReader methods. So for string, we have these two extensions, which allow for both column ordinal or name, whichever you have access to:
/// <summary>Checks for null before calling GetString.</summary>
/// <returns>The string value of the column, or null if the column is <see cref="DBNull"/>.</returns>
public static string GetNullableString(this IDataRecord row, int i)
{
object val;
if((val = row.GetValue(i)) == DBNull.Value)
return null;
return val.ToString();
}
/// <summary>Checks for null before calling GetString.</summary>
/// <returns>The string value of the column, or null if the column is <see cref="DBNull"/>.</returns>
public static string GetNullableString(this IDataRecord row, string name)
{
object val;
if((val = row[name]) == DBNull.Value)
return null;
return val.ToString();
}
and you could modify this to accept a replacement value for null, although we have extension methods that are string specific for that rather than at the DataReader level...again, just to separate concerns:
/// <summary>Checks for null before calling GetString.</summary>
/// <returns>The string value of the column, or <paramref name="defaultVal'/> if the column is <see cref="DBNull"/>.</returns>
public static string GetNullableString(this IDataRecord row, string name, string defaultVal)
{
object val;
if((val = row[name]) == DBNull.Value)
return defaultVal;
return val.ToString();
}