Null safe way to get values from an IDataReader
(LocalVariable)ABC.string(Name) = (IDataReader)dataReader.GetString(0);
This name
value is coming from database.
What happening here is if this name
is null
while reading it's throwing an exception?
I am manually doing some if condition he开发者_如何学运维re. I don't want to write a manual condition to check all my variables.
I am doing something like this now..
String abc = dataReader.GetValue(0);
if (abc == null)
//assigning null
else
//assigning abc value
Is there something like can we write extension method for this?
Here is a couple extension methods that will nicely wrap up all of your concerns around retrieving strongly typed values from a data reader. If the value is DbNull the default of the type will be returned. In the case of string
which is a class, a null
will be returned. If the field was int
, then 0
would be returned. Additionally, if you are expecting an int?
, say from an nullable int field, null
would be returned.
Specific Usage for Kumar's case:
string abc = datareader.GetValueOrDefault<string>(0);
General Usage
var name = GetValueOrDefault<string>(reader, "Name");
or
var name = reader.GetValueOrDefault<string>("Name");
or
var name = reader.GetValueOrDefault<string>(0);
Extension
public static class NullSafeGetter
{
public static T GetValueOrDefault<T>(this IDataRecord row, string fieldName)
{
int ordinal = row.GetOrdinal(fieldName);
return row.GetValueOrDefault<T>(ordinal);
}
public static T GetValueOrDefault<T>(this IDataRecord row, int ordinal)
{
return (T)(row.IsDBNull(ordinal) ? default(T) : row.GetValue(ordinal));
}
}
from http://skysanders.net/subtext/archive/2010/03/02/generic-nullsafe-idatarecord-field-getter.aspx
Similar to @sky-sanders answer but less strict with conversions:
public static T Get<T>(this IDataRecord row, string fieldName)
{
int ordinal = row.GetOrdinal(fieldName);
return row.Get<T>(ordinal);
}
public static T Get<T>(this IDataRecord row, int ordinal)
{
var value = row.IsDBNull(ordinal) ? default(T) : row.GetValue(ordinal);
return (T)Convert.ChangeType(value, typeof(T));
}
My solution is that:
private static T GetValue<T>(object o) {
if (typeof(DBNull) != o.GetType()) {
return (T) o;
}
return default(T);
}
When, Status = GetValue<string>(currentDataRow["status"])
Combining top solutions and suggestions, here is a C# 6 arrow expression version with support for GetValue<T>
and GetValueOrDefault<T>
with optional default value parameters.
public static class DataRecordExtensions {
/// <summary>
/// Generically extracts a field value by name from any IDataRecord as specified type. Will throw if DNE.
/// </summary>
public static T GetValue<T>(this IDataRecord row, string fieldName)
=> row.GetValue<T>(row.GetOrdinal(fieldName));
/// <summary>
/// Generically extracts a field value by ordinal from any IDataRecord as specified type. Will throw if DNE.
/// </summary>
public static T GetValue<T>(this IDataRecord row, int ordinal)
=> (T)row.GetValue(ordinal);
/// <summary>
/// Generically extracts a field value by name from any IDataRecord as specified type. Will return default generic types value if DNE.
/// </summary>
public static T GetValueOrDefault<T>(this IDataRecord row, string fieldName, T defaultValue = default(T))
=> row.GetValueOrDefault<T>(row.GetOrdinal(fieldName), defaultValue);
/// <summary>
/// Generically extracts a field value by ordinal from any IDataRecord as specified type. Will return default generic types value if DNE.
/// </summary>
public static T GetValueOrDefault<T>(this IDataRecord row, int ordinal, T defaultValue = default(T))
=> (T)(row.IsDBNull(ordinal) ? defaultValue : row.GetValue(ordinal));
}
I'd use something like this:
string abc = (IDataReader)datareader.GetValue(0) ?? "Default";
精彩评论