Search
Write a publication
Pull to refresh

ORM или простое наполнение класса данными из хранимой процедуры

Reading time4 min
Views2K
Привет всем хабраюзерам, решил написать первую свою статью, которая, продолжает серию очерков про взаимодействие с БД. Так случилось что подвернулся небольшой вэб-проект для реализации. В качестве платформы был выбран ASP.NET MVC + ExtJS но вот решение для ORM сходу не нашлось. Проблема заключалась в том что привлекать большое промышленное ORM решение типа NHibernate или Entity Framework не хотелось, так как проект будет иметь от силы два-три десятка хранимых процедур. Одновременно с этим использовать обвертку от Microsoft DAAB тоже не получается, т.к. в MVC фреймворке модели являются по сути копиями таблиц БД (ну просто для упрощения будем так считать) в результате Reader-ы, DataSet-ы и DataTable-ы нам мало чем могут помочь. Возможно хорошим решением было бы использовать LinqToSql, но мне очень не нравиться когда запросы написаны не на SQL а на C#, я твердо убеждён что общение между приложением и БД должно происходить только посредством хранимых процедур и функций. Другими словами нам нужен маппинг класа на result set хранимой процедуры и простота его использования, что бы просто вызвать хелпер-метод и он, используя рефлексию, вернул коллекцию экземпляров наполненными данными из процедуры. Думаю суть проблемы я изложил достаточно понятно итак приступим к реализации.

Для начала объявим наш класс который будем наполнять данными, само собой, что он будет полностью копировать поля которые возвращает хранимая процедура:
public class Book
{
 public int ID { get; set; }
 public string Title { get; set; }
 public string Author { get; set; }
 public DateTime PublicationDate { get; set; }
}


* This source code was highlighted with Source Code Highlighter.

А вот и хелпер-метод для маппинга:
public static List<T> GetSpResultset<T>(string spName)
{
  List<T> list = new List<T>();
  SqlConnection connection = new SqlConnection("строка соединения");
 
  connection.Open();

  using (SqlCommand command = new SqlCommand(spName, connection))
  {
   command.CommandType = CommandType.StoredProcedure;
   using (IDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
   {
    PropertyInfo[] fields = typeof(T).GetProperties();
    while (reader.Read())
    {
      T record = Activator.CreateInstance<T>();
      foreach (PropertyInfo pi in fields)
      {
       if (pi.PropertyType.Name == typeof(Int32).Name)
       {
        if (pi.CanWrite)
        {
         int value = reader.GetInt32(reader.GetOrdinal(pi.Name));
         pi.SetValue(record, value, null);
        }
       }
       else if (pi.PropertyType.Name == typeof(Int16).Name)
       {
        if (pi.CanWrite)
        {
         short value = Convert.ToInt16(reader.GetValue(reader.GetOrdinal(pi.Name)));
         pi.SetValue(record, value, null);
        }
       }
       else if (pi.PropertyType.Name == typeof(String).Name)
       {
        if (pi.CanWrite)
        {
         string value = reader.GetString(reader.GetOrdinal(pi.Name));
         pi.SetValue(record, value, null);
        }
       }
       else if (pi.PropertyType.Name == typeof(DateTime).Name)
       {
        if (pi.CanWrite)
        {
         DateTime value = reader.GetDateTime(reader.GetOrdinal(pi.Name));
         pi.SetValue(record, value, null);
        }
       }
      }
      list.Add(record);
    }
   }
  }
  return list;
}


* This source code was highlighted with Source Code Highlighter.

Метод реализован как generic method который возвращает коллекцию System.Collections.Generic.List&nbsp наполненную экземплярами нашего класса, для простоты реализации в нем опущена передача параметров в процедуру и реализована работа всего с 4 типами данных Int32, Int16, String и DateTime, но вы с легкость сможете его расширить и дополнить функционально.

Ну и конечно же пример использования:
List<Book> books = GetSpResultset<Book>("sp_GetBooks");

* This source code was highlighted with Source Code Highlighter.

Ну вот собственно и все что я хотел рассказать в своей статье, с нетерпением жду замечаний и конструктивной критики.
Tags:
Hubs:
Total votes 9: ↑7 and ↓2+5
Comments19

Articles