Another IDbCommand Extension - Fill
I'm on a roll creating extension methods for IDbCommand, so here's another one.
Quite often we see this pattern when reading from a command:
using (var rdr = cmd.ExecuteReader()) { while (rdr.Read()) { var thing = new Thing() { Date = rdr.GetDateTime(0), Foo = rdr.GetInt32(1) }; things.Add(thing); } }
It's pretty straight-forward code, but it's code nonetheless. Here's an extension method on IDbCommand that wraps this logic up into one call. It accepts an IList<T> as a parameter, and a function which, given an IDataReader, returns an instance of T:
public static void Fill<T>(this IDbCommand cmd, IList<T> list, Func<IDataReader, T> rowConverter) { using (var rdr = cmd.ExecuteReader()) { while (rdr.Read()) { list.Add(rowConverter(rdr)); } } }
This takes care of wrapping the reader in a "using" statement, so there's one less thing you have to remember to do. If you took the code in the first snippet and wrapped the call to GetDateTime and GetInt32 into its own little extension method on IDataReader called "GetThing", then you'd be able to turn that into this:
cmd.Fill(things, r => r.GetThing());The less code you have to write, the less the chance you'll introduce bugs, so for me this is a handy method. What do you think? Do you prefer to spell it out, or are extension methods ringing your bell too?
Comments
# Eric
12/07/2008 4:47 AM
It might be just me but all these lambada functions, method extensions, generics and vars are really making the C# language tough to read...
# willi
27/10/2011 6:52 PM
what about composite class like this
class Customer
{
private int _id;
private int _name;
private Company _company
...
}
class Company
{
private int _id;
private string _name;
...
}
Could your way solve this case?
# mabster
28/10/2011 7:50 AM
@willi Shouldn't be any different provided your query returns all the necessary information. Something like:
cmd.Fill(things, r =>
new Customer
{
Id = r.GetInt32(0),
Name = r.GetString(1),
Company = new Company
{
Id = r.GetInt32(2),
Name = r.GetString(3)
}
}