I\'m using a SQLdatareader to build POCOs from a database. The code works except when it encounters a null value in the database. For example, if the FirstName column in the
how to about creating helper methods
For String
private static string MyStringConverter(object o)
{
if (o == DBNull.Value || o == null)
return "";
return o.ToString();
}
Usage
MyStringConverter(read["indexStringValue"])
For Int
private static int MyIntonverter(object o)
{
if (o == DBNull.Value || o == null)
return 0;
return Convert.ToInt32(o);
}
Usage
MyIntonverter(read["indexIntValue"])
For Date
private static DateTime? MyDateConverter(object o)
{
return (o == DBNull.Value || o == null) ? (DateTime?)null : Convert.ToDateTime(o);
}
Usage
MyDateConverter(read["indexDateValue"])
Note: for DateTime declare varialbe as
DateTime? variable;
IsDbNull(int)
is usually much slower than using methods like GetSqlDateTime
and then comparing to DBNull.Value
. Try these extension methods for SqlDataReader
.
public static T Def<T>(this SqlDataReader r, int ord)
{
var t = r.GetSqlValue(ord);
if (t == DBNull.Value) return default(T);
return ((INullable)t).IsNull ? default(T) : (T)t;
}
public static T? Val<T>(this SqlDataReader r, int ord) where T:struct
{
var t = r.GetSqlValue(ord);
if (t == DBNull.Value) return null;
return ((INullable)t).IsNull ? (T?)null : (T)t;
}
public static T Ref<T>(this SqlDataReader r, int ord) where T : class
{
var t = r.GetSqlValue(ord);
if (t == DBNull.Value) return null;
return ((INullable)t).IsNull ? null : (T)t;
}
Use them like this:
var dd = r.Val<DateTime>(ords[4]);
var ii = r.Def<int>(ords[0]);
int nn = r.Def<int>(ords[0]);
reader.IsDbNull(ColumnIndex)
works as many answers says.
And I want to mention if you working with column names, just comparing types may be more comfortable.
if(reader["TeacherImage"].GetType() == typeof(DBNull)) { //logic }
and / or use ternary operator with assignment:
employee.FirstName = rdr.IsDBNull(indexFirstName))?
String.Empty: rdr.GetString(indexFirstName);
replace the default (when null) value as appropriate for each property type...
As an addition to the answer by marc_s, you can use a more generic extension method to get values from the SqlDataReader:
public static T SafeGet<T>(this SqlDataReader reader, int col)
{
return reader.IsDBNull(col) ? default(T) : reader.GetFieldValue<T>(col);
}
By influencing from getpsyched's answer, I created a generic method which checks column value by its name
public static T SafeGet<T>(this System.Data.SqlClient.SqlDataReader reader, string nameOfColumn)
{
var indexOfColumn = reader.GetOrdinal(nameOfColumn);
return reader.IsDBNull(indexOfColumn) ? default(T) : reader.GetFieldValue<T>(indexOfColumn);
}
Usage:
var myVariable = SafeGet<string>(reader, "NameOfColumn")