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 value is null while reading it's throwing an exception?

I am manually doing some if condition here. I don't want to write a manual condition to check all my variables..

I am doing something like this now..

string abc =  (Idatareader)datareader.GetValue(0);
if(abc = null)
    //assiging null
else
    assiging abc value

is there something like can we write extension method for this? thanks

Answers


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";

Need Your Help

Linking Container in AWS Fargate

amazon-web-services aws-fargate

I try to setup a little example on AWS Fargate and try to have one application container with one database container there.

How to display list of running processes Python?

python linux centos

How to display list of running processes Python with full name and active status?