IDataReader Extension Methods
First of all -- I'm a total liar. I was supposed to offer up some great insight from Tech•Ed. But alas, I had to leave early and fly to Seattle for a meeting. So, I wasn't able to share any fun stuff :(
We'll, I actually have a tiny bit of time to write, and I thought I'd share the result of recent code review.
I'm currently teaching .NET (Framework fundamentals, C#, et al.) to some of my clients who are preparing to take over the support of a very large application (we're going on 2 years of development and deployment!) As we were looking at some of the code, I came across some stuff from our offshore team that slipped by my team's radar. In this particular project, we found hundreds of lines that looked like this:
theatre.ID = (reader["theatre_id"] is DBNull) ?
0 : Convert.ToInt32(reader["theatre_id"]);
theatre.Code = (reader["theatre_code"] is DBNull) ?
String.Empty : reader["theatre_code"].ToString();
Ick! I was very bummed to come across this while teaching my clients about best practice -- was a bit 'the fool'. Not wanting to let this pass, I quickly redirected the discussion to talk about refactoring and reuse (which was kind of a nice segue to some OO topics.) In this discussion, we wrote an Extension Method to the IDataReader class to clean-up this code. The new code looked pretty:
theatre.ID = reader.GetValueOrDefault<int>("theatre_id");
theatre.Code = reader.GetValueOrDefault<string>("theatre_code");
The details of this Extension Method are as follows:
/// <SUMMARY>
/// Contains extension methods for the IDataReader interface.
/// </SUMMARY>
public static class DataReaderExtender
{
/// <SUMMARY>
/// This method will return the value of the specified columnName, cast to
/// the type specified in T. However, if the value found in the reader is
/// DBNull, this method will return the default value of the type T.
/// </SUMMARY>
/// <TYPEPARAM name="T">The type to which the value found in the reader should be cast.</TYPEPARAM>
/// <PARAM name="reader">The reader in which columnName is found.</PARAM>
/// <PARAM name="columnName">The columnName to retrieve.</PARAM>
/// <RETURNS>The column value within the reader typed as T.</RETURNS>
public static T GetValueOrDefault<T>(this IDataReader reader, string columnName)
{
object columnValue = reader[columnName];
T returnValue = default(T);
if (!(columnValue is DBNull))
{
returnValue = (T)Convert.ChangeType(columnValue, typeof(T));
}
return returnValue;
}
}
Enjoy! (I've posted the code here: DataReaderExtender.zip)