ORM
         На примерах NHibernate, Entity Framework, LINQ to SQL


Цуканов Павел
ptsukanov@codereign.net
Skype: cpp.tula
ORM это
• Object Relational Mapping = Объектно-
  ориентированная проекция
  (отображение)
• А если проще. Это возможность без
  больших затрат сохранять/считывать
  объекты в базе данных
Что было до ORM
Что стало после
А зачем это надо
• Меньше кода.
• Нет небходимости самому писать SQL
  запросы.
• Нет необходимости самому создавать
  объекты.
• Можно работать с имеющимся
  доменными/бизнес объектами.
• В конечном итоге это проще
  сопровождать.
5 причин использовать ORM
• Сокращает время разработки.
• Позволяет создать более лучший код.
• Нет необходимости быть экспертом .NET,
  что-бы использовать ORM.
• Сокращает время тестирования.
• Упрощает сопровождение.
Сокращает время
         разработки
• Сокращает вам кучу времени на разработку от
  20% до 50% (в зависимости от проектов).
• Типично для 15-20 таблиц это 30-50 объектов,
  а это примерно от 5000 до 10000 строк кода. И
  это надо написать и протестировать.
• С ORM тоже можно сделать за 1-2 дня. Причём
  основное время потребуется на обдумывание
  как осуществить маппирование корректно.
Позволяет создать более
        лучший код.
• Разные люди в команде могут создать свой
  уникальный код для преобразования объектов
  из/в БД, опираясь исключительно на свой опыт.
• ORM использует шаблоны кода, которые имеют
  отличный дизайн. Причем, эти шаблоны кода
  почти всегда следуют известным шаблонам
  проектирования. Таким образом, код, который
  вы будете получать от ORM очень вероятно,
  будет лучше разработаны, чем код,
  разработанный собственной командой.
Нет необходимости быть
         экспертом .NET, что-бы
         использовать ORM.
• Вы можете начать использовать ORM очень
  быстро имея лишь поверхностные знания.
• Удивительно, но это факт, подчеркнутый
  из собственного опыта.
• При этом ваш код не будет сильно
  отличаться от экспертов в этом вопросе.
• Хотя конечно, есть и подводные камни.
Сокращает время
         тестирования.
• Вам нет необходимости вручную
  преобразовывать объекты из/в базу
  данных. А следовательно нет
  необходимости тестировать того чего нет.
• Код который делает такое преобразование
  написан за вас и уже протестирован.
Упрощает
          сопровождение.
• Жизнь программы не заканчивается
  выпуском релиза. Она живёт и
  развивается и изменение кода в случае с
  ORM менее затратное занятие. Так как вы
  написали меньше кода
• Разработчик знающий как функционирует
  та или иная ORM может без проблем
  переключится с проекта на проект и
  понять как тут всё устроено.
Что у нас есть
• LINQ to SQL (
  http://msdn.microsoft.com/en-en/library/bb386976.aspx
  )
• Entity Framework (
  http://msdn.microsoft.com/en-en/library/bb399572.aspx
  )
• Nhibernate (http://nhforge.org)
• eXpressPersistent Objects™ (
  http://www.devexpress.com/products/NET/XPO)
• LLBLGen Pro (http://www.llblgen.com)
• Dapper.NET (
  http://code.google.com/p/dapper-dot-net/)(ORM
  сайта StackOverflow).
LINQ to SQL


• Входит в состав .Net Framework начиная с
  3.5.
• Разработано спецально для работы с MSSQL
  сервером через LINQ.
• Отказано в развитии.
Entity Framework

• Входит в состав .Net Framework начиная
  с 3.5
• С .Net Framework 4.0 это рекомендуемый
  способ доступа к БД через Linq
• Последняя версия 5.0 находится в бетта
  версии и будет доступна с .Net
  Framework 4.5
• ORM-решение для платформы Microsoft .NET
  портированное с Java.
• Бесплатная библиотека модно найти на
  http://nhforge.org
• Последняя версия 3.2
Сравним
1    Сложность
• LINQ to SQL – Самая лёгкая и простая
• Entity Framework – Более сложная.
  Визуальный интерфейс позволяет сделать
  сложные вещи очень просто.
• NHibernate – Наиболее продвинутая ORM
  из вышеперечисленных
2     Наследование
• LINQ to SQL – Table per Class Hierarchy
  (TPH).
• Entity Framework – несколько видов
  наследования Table per Class Hierarchy
  (TPH), Table per Type (TPT), and Table per
  Concrete Class (TPC).
• NHibernate – дополнительно к NHibernate
  - Implicit polymorphism
TPH (Table per Class Hierarchy )
TPT (Table per Type)
TPC (Table per Concrete Class)
Implicit polymorphism

public static List<Object> GetAll()
{
   List<Object> objects = session.find(“from Object”);
   return objects;
}
3    Поддержка БД
• LINQ to SQL – MSSQL2000 и старше.
• Entity Framework – MSSQL, IBM DB2, Sybase
  SqlAnywhere, Oracle, SQL Azure и многие
  другие. Главное чтобы был ADO.Net Data
  provider для соответствующей БД.
• NHibernate – Microsoft SQL Server
  2005/2000, Oracle, Microsoft Access,
  Firebird, PostgreSQL, DB2 UDB, MySQL,
  SQLite. Определяется наличием
  соответствующего драйвера у NHibernate.
4     Сложность разработки
• LINQ to SQL – прост в обучении и при
  разработке простых приложений.
• Entity Framework – более сложная
  библиотека и требует время на изучение всех
  ньюансов. Рекомендуется как для простых так
  и сложных приложений.
• NHibernate – Достаточно сложная в изучении
  чем Entity Framework. Однако гибкость
  конфигурирования позволяет легко
  сопровождать приложения. Рекомендую для
  сложных проектов.
Типы используемых
 5     файлов
• LINQ to SQL – файл DBML – содержит XML
  маппинг классов к таблицам
• Entity Framework – обычно EDMX файл
  генерируется во время разработки.
  Остальные CSDL, SSDL, MSL файлы во
  время компиляции.
• NHibernate – XML файлы конфигурации.
Поддержка комплексных
  6     типов
• LINQ to SQL – нет
• Entity Framework – да
• NHibernate – нет.
7      Поддержка LINQ
• LINQ to SQL – да. Основной способ работы
  с базой данных.
• Entity Framework – да. Основной способ
  работы с базой данных.
• NHibernate – да, но в ограниченном
  объёме (во всяком случае в NH 2.0).
8     Производительность
• Cчитается что как ни странно Entity
  Framework – быстрее чем LINQ to SQL.
• NHibernate – позволяет добиться более
  высокой производительности при более
  тонкой настройке.
9      Будущее библиотек
• LINQ to SQL – не развивается.
• Entity Framework – активно развивается и
  конечном итоге дожна заменить LINQ to
  SQL.
• NHibernate – развивается пока есть
  энтузиасты.
Генерация кода из БД и
 10     наоборот
• LINQ to SQL – генерирует классы из БД.
• Entity Framework – генерирует классы из
  БД и наоборот
• NHibernate – всё ручками.
Работа с POCO (Plain Old CLR
 11     Objects) объектами
• LINQ to SQL – работает, но с натяжкой.
• Entity Framework – да
• NHibernate – да.
12     Способы маппирования
• LINQ to SQL – через атрибуты.
• Entity Framework – через аттрибуты, XML
  файлы
• NHibernate – через аттрибуты, XML файлы,
  Fluent NHibernate.
13     Кэширование
• LINQ to SQL – Кэш 1-го уровня.
• Entity Framework – Кэш 1-го уровня. Кэш
  2-го уровня через обертки (
  http://code.msdn.microsoft.com/EFProviderWrappers
  )
• NHibernate – Есть кэши 1-го и 2-го уровня.
Кэш 1-го уровня
[Test]
public void trying_to_get_the_same_account_a_second_........... ()
{
         Console.WriteLine("------ now getting entity for the first time");
         var acc1 = Session.Get<Account>(account.Id);
         Console.WriteLine("------ now getting entity for the second time");
         var acc2 = Session.Get<Account>(account.Id); 
         acc1.ShouldBeTheSameAs(acc2);
}
Без кэша 2-го уровня
[Test]
public void trying_to_load_an_existing_item_twice_in_................. ()
{
  using(var session = SessionFactory.OpenSession())
  {
     var acc = session.Get<Account>(account.Id);
     acc.ShouldNotBeNull();
  }

    using(var session = SessionFactory.OpenSession())
    {
       var acc = session.Get<Account>(account.Id);
       acc.ShouldNotBeNull();
    }
}
Без кэша 2-го уровня
С кэшем 2-го уровня
[Test]
public void when_updating_the_entity_then_2nd_level.......... ()
{
  using(var session = SessionFactory.OpenSession())
  using (var tx = session.BeginTransaction())
  {
     var acc = session.Get<Account>(account.Id);
     acc.Credit(200m);
     tx.Commit();
  }

    using(var session = SessionFactory.OpenSession())
    {
       var acc = session.Get<Account>(account.Id);
       acc.Balance.ShouldEqual(1200m);
    }
}
С кэшем 2-го уровня
Провайдеры кэша 2-го
                        уровня
• Velocity: использует Microsoft Velocity (
  http://msdn.microsoft.com/en-us/data/cc655792.aspx)
• Prevalence: использует Bamboo.Prevalence (
  http://bbooprevalence.sourceforge.net/)
• SysCache: использует System.Web.Caching.Cache.
• SysCache2: подобно SysCache но с более продвинутуми
  настройками кэширования.
• MemCache: использует memcached (
  http://www.danga.com/memcached/).
• SharedCache: смотри (
  http://www.codeplex.com/SharedCache) и
  http://www.sharedcache.com/cms/
14    API
• LINQ to SQL и Entity Framework имеют
  менее богатый API чем NHibernate
• Например NHibernate имеет
  − Перехватчик запросов, вставки, удаления и
    обновления
  − Перехватчик создания объекта
  − Логгирование с использованием log4net.
Проблемы
• Скрытие БД ведёт к деградации производительности.
• Баги в библиотеке ведёт к нетривиальным методам
  решений.
• Иерархия классов может привести к блокировкам в БД и
  как следствие к деградации производительности.
• Загрузка классов, содержащие в полях экземпляры
  других (сохраняемых также через ORM) классов. Может
  привести к длительному процессу.
Заключение

• Каждый вправе выбирать ORM себе по
  вкусу. Так как нет универсального
  решения.
• Для маленьких проектов я бы предпочёл
  LINQ to SQL или Entity Framework.
• Для средних Entity Framework и
  NHibernate.
• Для больших только NHibernate.
Пожалуйста, Ваши Вопросы!!!

ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)

  • 1.
    ORM На примерах NHibernate, Entity Framework, LINQ to SQL Цуканов Павел ptsukanov@codereign.net Skype: cpp.tula
  • 2.
    ORM это • ObjectRelational Mapping = Объектно- ориентированная проекция (отображение) • А если проще. Это возможность без больших затрат сохранять/считывать объекты в базе данных
  • 3.
  • 4.
  • 5.
    А зачем этонадо • Меньше кода. • Нет небходимости самому писать SQL запросы. • Нет необходимости самому создавать объекты. • Можно работать с имеющимся доменными/бизнес объектами. • В конечном итоге это проще сопровождать.
  • 6.
    5 причин использоватьORM • Сокращает время разработки. • Позволяет создать более лучший код. • Нет необходимости быть экспертом .NET, что-бы использовать ORM. • Сокращает время тестирования. • Упрощает сопровождение.
  • 7.
    Сокращает время разработки • Сокращает вам кучу времени на разработку от 20% до 50% (в зависимости от проектов). • Типично для 15-20 таблиц это 30-50 объектов, а это примерно от 5000 до 10000 строк кода. И это надо написать и протестировать. • С ORM тоже можно сделать за 1-2 дня. Причём основное время потребуется на обдумывание как осуществить маппирование корректно.
  • 8.
    Позволяет создать более лучший код. • Разные люди в команде могут создать свой уникальный код для преобразования объектов из/в БД, опираясь исключительно на свой опыт. • ORM использует шаблоны кода, которые имеют отличный дизайн. Причем, эти шаблоны кода почти всегда следуют известным шаблонам проектирования. Таким образом, код, который вы будете получать от ORM очень вероятно, будет лучше разработаны, чем код, разработанный собственной командой.
  • 9.
    Нет необходимости быть экспертом .NET, что-бы использовать ORM. • Вы можете начать использовать ORM очень быстро имея лишь поверхностные знания. • Удивительно, но это факт, подчеркнутый из собственного опыта. • При этом ваш код не будет сильно отличаться от экспертов в этом вопросе. • Хотя конечно, есть и подводные камни.
  • 10.
    Сокращает время тестирования. • Вам нет необходимости вручную преобразовывать объекты из/в базу данных. А следовательно нет необходимости тестировать того чего нет. • Код который делает такое преобразование написан за вас и уже протестирован.
  • 11.
    Упрощает сопровождение. • Жизнь программы не заканчивается выпуском релиза. Она живёт и развивается и изменение кода в случае с ORM менее затратное занятие. Так как вы написали меньше кода • Разработчик знающий как функционирует та или иная ORM может без проблем переключится с проекта на проект и понять как тут всё устроено.
  • 12.
    Что у насесть • LINQ to SQL ( http://msdn.microsoft.com/en-en/library/bb386976.aspx ) • Entity Framework ( http://msdn.microsoft.com/en-en/library/bb399572.aspx ) • Nhibernate (http://nhforge.org) • eXpressPersistent Objects™ ( http://www.devexpress.com/products/NET/XPO) • LLBLGen Pro (http://www.llblgen.com) • Dapper.NET ( http://code.google.com/p/dapper-dot-net/)(ORM сайта StackOverflow).
  • 13.
    LINQ to SQL •Входит в состав .Net Framework начиная с 3.5. • Разработано спецально для работы с MSSQL сервером через LINQ. • Отказано в развитии.
  • 14.
    Entity Framework • Входитв состав .Net Framework начиная с 3.5 • С .Net Framework 4.0 это рекомендуемый способ доступа к БД через Linq • Последняя версия 5.0 находится в бетта версии и будет доступна с .Net Framework 4.5
  • 15.
    • ORM-решение дляплатформы Microsoft .NET портированное с Java. • Бесплатная библиотека модно найти на http://nhforge.org • Последняя версия 3.2
  • 16.
  • 17.
    1 Сложность • LINQ to SQL – Самая лёгкая и простая • Entity Framework – Более сложная. Визуальный интерфейс позволяет сделать сложные вещи очень просто. • NHibernate – Наиболее продвинутая ORM из вышеперечисленных
  • 18.
    2 Наследование • LINQ to SQL – Table per Class Hierarchy (TPH). • Entity Framework – несколько видов наследования Table per Class Hierarchy (TPH), Table per Type (TPT), and Table per Concrete Class (TPC). • NHibernate – дополнительно к NHibernate - Implicit polymorphism
  • 19.
    TPH (Table perClass Hierarchy )
  • 20.
  • 21.
    TPC (Table perConcrete Class)
  • 22.
    Implicit polymorphism public staticList<Object> GetAll() { List<Object> objects = session.find(“from Object”); return objects; }
  • 23.
    3 Поддержка БД • LINQ to SQL – MSSQL2000 и старше. • Entity Framework – MSSQL, IBM DB2, Sybase SqlAnywhere, Oracle, SQL Azure и многие другие. Главное чтобы был ADO.Net Data provider для соответствующей БД. • NHibernate – Microsoft SQL Server 2005/2000, Oracle, Microsoft Access, Firebird, PostgreSQL, DB2 UDB, MySQL, SQLite. Определяется наличием соответствующего драйвера у NHibernate.
  • 24.
    4 Сложность разработки • LINQ to SQL – прост в обучении и при разработке простых приложений. • Entity Framework – более сложная библиотека и требует время на изучение всех ньюансов. Рекомендуется как для простых так и сложных приложений. • NHibernate – Достаточно сложная в изучении чем Entity Framework. Однако гибкость конфигурирования позволяет легко сопровождать приложения. Рекомендую для сложных проектов.
  • 25.
    Типы используемых 5 файлов • LINQ to SQL – файл DBML – содержит XML маппинг классов к таблицам • Entity Framework – обычно EDMX файл генерируется во время разработки. Остальные CSDL, SSDL, MSL файлы во время компиляции. • NHibernate – XML файлы конфигурации.
  • 26.
    Поддержка комплексных 6 типов • LINQ to SQL – нет • Entity Framework – да • NHibernate – нет.
  • 27.
    7 Поддержка LINQ • LINQ to SQL – да. Основной способ работы с базой данных. • Entity Framework – да. Основной способ работы с базой данных. • NHibernate – да, но в ограниченном объёме (во всяком случае в NH 2.0).
  • 28.
    8 Производительность • Cчитается что как ни странно Entity Framework – быстрее чем LINQ to SQL. • NHibernate – позволяет добиться более высокой производительности при более тонкой настройке.
  • 29.
    9 Будущее библиотек • LINQ to SQL – не развивается. • Entity Framework – активно развивается и конечном итоге дожна заменить LINQ to SQL. • NHibernate – развивается пока есть энтузиасты.
  • 30.
    Генерация кода изБД и 10 наоборот • LINQ to SQL – генерирует классы из БД. • Entity Framework – генерирует классы из БД и наоборот • NHibernate – всё ручками.
  • 31.
    Работа с POCO(Plain Old CLR 11 Objects) объектами • LINQ to SQL – работает, но с натяжкой. • Entity Framework – да • NHibernate – да.
  • 32.
    12 Способы маппирования • LINQ to SQL – через атрибуты. • Entity Framework – через аттрибуты, XML файлы • NHibernate – через аттрибуты, XML файлы, Fluent NHibernate.
  • 33.
    13 Кэширование • LINQ to SQL – Кэш 1-го уровня. • Entity Framework – Кэш 1-го уровня. Кэш 2-го уровня через обертки ( http://code.msdn.microsoft.com/EFProviderWrappers ) • NHibernate – Есть кэши 1-го и 2-го уровня.
  • 34.
    Кэш 1-го уровня [Test] publicvoid trying_to_get_the_same_account_a_second_........... () { Console.WriteLine("------ now getting entity for the first time"); var acc1 = Session.Get<Account>(account.Id); Console.WriteLine("------ now getting entity for the second time"); var acc2 = Session.Get<Account>(account.Id);  acc1.ShouldBeTheSameAs(acc2); }
  • 35.
    Без кэша 2-гоуровня [Test] public void trying_to_load_an_existing_item_twice_in_................. () { using(var session = SessionFactory.OpenSession()) { var acc = session.Get<Account>(account.Id); acc.ShouldNotBeNull(); } using(var session = SessionFactory.OpenSession()) { var acc = session.Get<Account>(account.Id); acc.ShouldNotBeNull(); } }
  • 36.
  • 37.
    С кэшем 2-гоуровня [Test] public void when_updating_the_entity_then_2nd_level.......... () { using(var session = SessionFactory.OpenSession()) using (var tx = session.BeginTransaction()) { var acc = session.Get<Account>(account.Id); acc.Credit(200m); tx.Commit(); } using(var session = SessionFactory.OpenSession()) { var acc = session.Get<Account>(account.Id); acc.Balance.ShouldEqual(1200m); } }
  • 38.
  • 39.
    Провайдеры кэша 2-го уровня • Velocity: использует Microsoft Velocity ( http://msdn.microsoft.com/en-us/data/cc655792.aspx) • Prevalence: использует Bamboo.Prevalence ( http://bbooprevalence.sourceforge.net/) • SysCache: использует System.Web.Caching.Cache. • SysCache2: подобно SysCache но с более продвинутуми настройками кэширования. • MemCache: использует memcached ( http://www.danga.com/memcached/). • SharedCache: смотри ( http://www.codeplex.com/SharedCache) и http://www.sharedcache.com/cms/
  • 40.
    14 API • LINQ to SQL и Entity Framework имеют менее богатый API чем NHibernate • Например NHibernate имеет − Перехватчик запросов, вставки, удаления и обновления − Перехватчик создания объекта − Логгирование с использованием log4net.
  • 41.
    Проблемы • Скрытие БДведёт к деградации производительности. • Баги в библиотеке ведёт к нетривиальным методам решений. • Иерархия классов может привести к блокировкам в БД и как следствие к деградации производительности. • Загрузка классов, содержащие в полях экземпляры других (сохраняемых также через ORM) классов. Может привести к длительному процессу.
  • 42.
    Заключение • Каждый вправевыбирать ORM себе по вкусу. Так как нет универсального решения. • Для маленьких проектов я бы предпочёл LINQ to SQL или Entity Framework. • Для средних Entity Framework и NHibernate. • Для больших только NHibernate.
  • 43.