2

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 :)

4
  • 3
    You could put that code into an extension method on the DbDataReader. That way, the horrible-looking code it hidden away behind a nicer looking GetNullableInt32() call. Commented Oct 26, 2010 at 8:24
  • 1
    @adrianbanks your comment deserves to be an answer!! Commented Oct 26, 2010 at 8:26
  • 1
    @adrianbanks: You should make that an answer, not a comment... Commented Oct 26, 2010 at 8:27
  • Only tangentially related, but you can use 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. Commented Oct 26, 2010 at 8:29

3 Answers 3

6

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;
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

It is better if you only call GetOrdinal(columnName) once.
@Ian: I agree (I used Palantir's original code to demonstrate how to make it into an extension method).
3

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);
   }
}

Comments

0

Not really. I often put this code in a method and call it. That method could end up in a common "helper" class or I suppose even an extension method (though I'm not personally a fan of those because they're hard for other people to discover).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.