I\'m using a third party library which returns a data reader. I would like a simple way and as generic as possible to convert it into a List of objects.
For example, say
We have implemented the following solution and feel it works pretty well. It's pretty simple and requires a bit more wiring up then what a mapper would do. However, sometimes it is nice to have the manual control and honestly, you wire up once and you're done.
In a nutshell: Our domain models implement an interface that has a method that takes in an IDataReader and populates the model properties from it. We then use Generics and Reflection to create an instance of the model and call the Parse method on it.
We considered using a constructor and passing IDataReader to it, but the basic performance checks we did seemed to suggest the interface was consistently faster (if only by a little). Also, the interface route provides instant feedback via compilation errors.
One of the things I like, is that you can utilize private set for properties like Age in the example below and set them straight from the database.
public interface IDataReaderParser
{
void Parse(IDataReader reader);
}
public class Foo : IDataReaderParser
{
public string Name { get; set; }
public int Age { get; private set; }
public void Parse(IDataReader reader)
{
Name = reader["Name"] as string;
Age = Convert.ToInt32(reader["Age"]);
}
}
public class DataLoader
{
public static IEnumerable GetRecords(string connectionStringName, string storedProcedureName, IEnumerable parameters = null)
where TEntity : IDataReaderParser, new()
{
using (var sqlCommand = new SqlCommand(storedProcedureName, Connections.GetSqlConnection(connectionStringName)))
{
using (sqlCommand.Connection)
{
sqlCommand.CommandType = CommandType.StoredProcedure;
AssignParameters(parameters, sqlCommand);
sqlCommand.Connection.Open();
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
//Create an instance and parse the reader to set the properties
var entity = new TEntity();
entity.Parse(sqlDataReader);
yield return entity;
}
}
}
}
}
}
To call it, you simply provide the type parameter
IEnumerable foos = DataLoader.GetRecords(/* params */)