I decided it was high time I did a post with some actual code samples in it, so here we go.
I am really enjoying some of the new C# 3.0 language features, one in particular is extensions methods. If you are not yet familiar with extension methods, ScottGu has a
good overview. I want to highlight some specific extension methods I've created for
IDataRecord that I think are extremely handy, especially when you spend a lot of time working in the data layer with DataReaders like I do. I feel like I've written variations on the same data layer 100 times. Every time it evolves, when I went from .Net 1.1 to 2.0 I took heavy advantage of generics. Now in .Net 3.5 I am simplifying it even more with extensions.
When working with DataReaders you might often have a ton of code that looks like this:
string myString = record.GetString(record.GetOrdinal("MyField"));
Where
record
is an IDataRecord coming from a SqlDataReader or something similar. Now that's not a terrible line of code, but it gets pretty annoying typing record.GetOrdinal all the time. So to save me that annoyance I've added the following to my IDataRecordExtensions class:
public static long GetString(this IDataRecord record, string field)
{
return record.GetString(record.GetOrdinal(field));
}
An now all I have to call in my record handling code is this:
string myString = record.GetString("MyField");
Not ground-breaking, but better, and you can write an extension for all the types you are getting data for. Here's a better example of how extension methods for your IDataRecord can be more useful. Sometimes you might be dealing with a nullable type, IDataRecord doesn't handle this too gracefully, you end up having to write code that looks something like this:
string myString = null;
int ordinal = record.GetOrdinal("MyField");
if(!record.IsDBNull(ordinal))
{
myString = record.GetString(ordinal);
}
Again, not a ton of code, but if you have to do this hundreds of times it's going to get annoying and you are going to make mistakes. Now check this out, in my IDataRecordExtensions class I add the following two methods:
private static T GetNullable<T>(IDataRecord record, string field, Func<int, T> func)
{
T result = default(T);
int ordinal = record.GetOrdinal(field);
if (!record.IsDBNull(ordinal))
{
result = func(ordinal);
}
return result;
}
public static String GetNullableString(this IDataRecord record, string field)
{
return GetNullable<string>(record, field, x => record.GetString(x));
}
OK, what the heck is going on here. Lets look at
GetNullableString
first. This is an extension method for an IDataRecord that takes a field name and then calls this private
GetNullable
method. Check out that third argument though. In
GetNullable
its defined as
Func<int, T> func
. What we are doing is taking advantage of lambda support in C# 3.0 and we are saying, pass me a function that takes an
int
and returns me a generic
T
, and in this case
T
is a string.
x => record.GetString(x)
is saying passing the record's
GetString
method as that parameter. Now in our data handling code we can just write:
string myString = record.GetNullableString("MyField");
Nice. What's even better, is now we can easily add other extensions for other more interesting nullable types, such as
double
by adding code like this to the IDataRecordExtensions class:
public static double? GetNullableDouble(this IDataRecord record, string field)
{
return GetNullable<double?>(record, field, x => record.GetDouble(x));
}
So there you go. Hopefully my experiences with extension methods and IDataRecord are helpful to others.