Lately I find myself writing data access layer select methods where the code all takes this general form:
public static DataTable GetSomeData( ... arguments)
Similar to what I posted here
public IEnumerable Get(string query, Action parameterizer,
Func selector)
{
using (var conn = new T()) //your connection object
{
using (var cmd = conn.CreateCommand())
{
if (parameterizer != null)
parameterizer(cmd);
cmd.CommandText = query;
cmd.Connection.ConnectionString = _connectionString;
cmd.Connection.Open();
using (var r = cmd.ExecuteReader())
while (r.Read())
yield return selector(r);
}
}
}
I have these simple extension methods to aid ease of calling:
public static void Parameterize(this IDbCommand command, string name, object value)
{
var parameter = command.CreateParameter();
parameter.ParameterName = name;
parameter.Value = value;
command.Parameters.Add(parameter);
}
public static T To(this IDataRecord dr, int index, T defaultValue = default(T),
Func
So now I can call:
var query = Get(sql, cmd =>
{
cmd.Parameterize("saved", 1);
cmd.Parameterize("name", "abel");
}, r => new User(r.To(0), r.To(1), r.To(2), r.To(3)));
foreach (var user in query)
{
}
This is fully generic, fits any model that comply to ado.net interfaces. The connection object and reader is disposed only after the collection is enumerated once.