Мы внедрили следующее решение и считаем, что оно работает довольно хорошо. Это довольно просто и требует немного больше проводки, чем то, что сделал бы картограф. Однако иногда приятно иметь ручное управление и, честно говоря, вы подключаетесь один раз и все готово.
В двух словах: Наши доменные модели реализуют интерфейс, который имеет метод, который принимает IDataReader
и заполняет из него свойства модели. Затем мы используем Generics и Reflection для создания экземпляра модели и вызываем для нее метод Parse
.
Мы рассмотрели возможность использования конструктора и передачи ему IDataReader
, но проведенные нами базовые проверки производительности, казалось, предполагали, что интерфейс был последовательно быстрее (хотя бы немного). Кроме того, интерфейсный маршрут обеспечивает мгновенную обратную связь через ошибки компиляции.
Мне нравится то, что вы можете использовать private set
для таких свойств, как Age
в приведенном ниже примере, и устанавливать их прямо из базы данных.
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<TEntity> GetRecords<TEntity>(string connectionStringName, string storedProcedureName, IEnumerable<SqlParameter> 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;
}
}
}
}
}
}
Чтобы вызвать его, вы просто указываете параметр типа
IEnumerable<Foo> foos = DataLoader.GetRecords<Foo>(/* params */)