понедельник, 9 марта 2009 г.

Влюбляемся в Entity Framework: Шаг первый: Введение

Пролог
Этот пост является началом цикла статей по Entity Framework, идея написания которого преследует меня уже достаточно продолжительное время.

Что побудило меня на это начинание?

Во-первых, мне нравятся ORM-системы (со всеми своими достоиствами и недостатками).
Во-вторых, несмотря на то, что мне приходится иметь дело с разными ORM, c Entity Framework меня связывают особенное теплые отношения :)
В-третьих, уже прошло более полугода с момента релиза EF v. 1 (а с моменты появления стабильных бета-версий - и того больше), а материалов в русскоговорящем сообществе до сих пор довольно мало. Здесь я хотел бы отметить статьи Сергея Розовика в блоге stump-workshop.blogspot.com (справа в блоке "Темы" выберите "Entity Framework"). Вероятно, я еще не раз буду ссылаться на эти статьи, дабы не повторяться.

Я сомневался, как писать этот цикл статей: последовательно от простого к сложному или как набор постов, описывающих определенные подходы и решающих конкретные задачи. С одной стороны, хочется, как можно скорее, поделиться интересными мыслями и наработками (это аргументы в пользу второго варианта), с другой, - ввиду отсутствия обширной информации по EF на русском языке, гораздо более уместным мне видится первый вариант. На нем и остановился.

Прежде чем приступить к введению, хотел бы отметить, что стиль именования статей я позаимствовал у Дмитрия Сошникова (с его разрешения). Со статьями Дмитрия Вы можете ознакомиться в его блоге на Хабре.

Введение
Итак, что же такое Entity Framework? EF - это реализация фирмы Microsoft технологии Object-relational Mapping (ORM) под .NET.

Так сложилось, что в области обработки данных (data management) мэйнстримом являются объектно-ориентированные языки программирования, а в области хранения данных (data storing) - реляционные базы данных (РБД).

ORM - это подход, позволяющий конвертировать данные между реляционными базами данных и объектно-ориентированными языками программирования, тем самым нивелируя так называемый object-relational impedance mismatch (по-русски это звучит не очень лаконично, вроде "несоответствие принципов, лежащих в основе объектного и реляционного подходов", поэтому позволю себе использовать английский вариант).

Рассмотрим ряд различий между объектной и реляционной концепциями:
  1. Различия в базовых принципах. ООП базируется на принципах создания программного обеспечения (инкапсуляция, наследование, полиморфизм), в то время как реляционная парадигма имеет в основе математические правила (операции с множествами). Если инкапсулацию и полиморфизм на уровне РБД представить невозможно (да, наверное, и не нужно), то с наследованием ORM справляются на отлично.
  2. Различия в оперируемых сущностях. В ООП мы оперируем объектами и ссылками на объекты, а в РБД - таблицами, атрибутами и записями. ORM с блеском нивелирует это различие, позволяя программисту обращаться к связанным объектам традиционными для ООП способами, лишая программиста "удовольствия" создания разнообразных join-запросов.
  3. Различия в оперируемых типах (эта проблема не является уникальной для взаимодействия объектной и реляционной систем: с ней приходится сталкиваться даже при взаимодействии двух объектно-ориентированных платформ, например, через Web-сервисы). В качестве примера обычно приводят тип данных "строка". Реляционные базы данных позволяют ограничивать размер строк, тогда как в большинстве объектно-ориентированных языков размер строки ограничивается лишь объемом доступной виртуальной памяти. В любом случае конвертация типов - рутинная работа, которую лучше автоматизировать за счет использования ORM.
Безусловно, на этом отличия не заканчиваются. Но, думаю, этого достаточно для того, чтобы понять, что ORM-системы появились не на ровном месте, и имеют право на существование.

Кроме того, ORM-системы направлены не только на борьбу с object-relational impedance mismatch, они предлагают и ряд других полезных возможностей (набор таких возможностей индивидуален для каждой конкретной реализации). Так, например, ORM позволяют генерировать SQL-запросы налету: Вы выполняете определенные операции с сущностями, отдаете команду ORM-системе, а она генерирует SQL-запрос и отдает его на выполнение. Это ли не чудо?! Больше не нужно писать рутинный код для работы с базой данных! Больше не нужно судорожно делать бесконечные Find&Replace при малейших изменениях схемы базы! Больше не нужно...

Стоит отметить, что до появления ORM (Hibernate 1.0 датирован лишь 2002 годом) программисты зачастую создавали свои собственные утилиты, которые по возможностям очень напоминали сегодняшние ORM. Таким образом, появление серьезных ORM стало не революцией, а, скорее, эволюцией, качественным улучшением средств реализации слоя доступа к данным.

Противники скрещивания ужа (объектной парадигмы) с ежом (реляционной парадигмой) совершенно справедливо указывают на то, что более логичным и лежащим на поверхности решением object-relational impedance mismatch был бы переход на объектно-ориентированные базы данных (ООБД). Однако, несмотря на то, что идея ООБД не нова (начало 70-х годов 20-го века), позиции объектно-ориентированных СУБД очень шатки. Причин на то много, но самая существенная, на мой взгляд, - как раз прочность позиций РБД.

Дабы обратить внимание на другие парадигмы, решил привести ссылку на пост двухгодичной давности с Enfranchised Mind, посвященный functional-relational impedance mismatch. Если я все правильно понял, описываемое там решение уже реализовано в .NET, и имя ему - Linq (в случае EF - Linq To Entities). Однако этот пост подтолкнул меня к дальнейшим размышлениям, в ходе которых я пришел к тому, что ORM - верный путь, ибо не напасешься СУБД, заточенных под каждую конкретную парадигму (все-таки ORM-система и СУБД - не сопоставимые по сложности задачи). А затем я вспомнил то, как ужасно ведут себя объемные RDF-хранилища, реализуемые на базе реляционных СУБД (лирическое отступление на тему Semantic Web). А все потому, что реляционая парадигма совершенно не отражает принципы, заложенные в онтологии (так, например, такая мощная возможность СУБД, как индексы, вынуждена простаивать без дела).

Так что мнение "лучше использовать ORM, чем внедрять объектно-ориентированную СУБД" актуально лишь для мэйнстримовых (на данный момент) задач. При решении же более узкоспециализированных задач возможны и диаметрально-противоположные мнения.

P. S.
Категорически приветствую критику. Если Вы заметили, что я ошибся, допустил неточность, или Вам кажется, что какой-то момент нужно рассмотреть более детально, - оставляйте комментарии или пишите на e-mail (указан в профиле).

9 комментариев:

Анонимный комментирует...

Похоже, что "парадигма" - это любимое слово программистов

Анонимный комментирует...

Стоит отметить, что до появления ORM (Hibernate 1.0 датирован лишь 2002 годом) программисты зачастую создавали свои собственные утилиты, которые по возможностям очень напоминали сегодняшние ORM.
--------------------
Сидоров - поменяйте стиль изложения. Сейчас - уровень сочинения ученика 5-го класса

Idsa комментирует...

Anonymous, чем богаты...

Обращение по фамилии - часть вашего уникального стиля? В следующий раз не забудьте авторизоваться.

Анонимный комментирует...

Прочитал статью от начала до конца, но так и не понял, что за радость EF.

Лично мое мнение, чем больше автоматизированных средств программирования, тем меньше будет слесарей на заводах :) Нет ничего страшного в написании sql запросов и острой необходимости в EF я тоже не вижу, ровным счетом как и в Linq :-D. Все это сахар, разбавляющий порой не очень сладкую жизнь программиста.

Анонимный комментирует...

Спасибо Александр, пожалуйста продолжайте работу по этому циклу статей.

Было бы очень интересно увидеть работу с Entity Framework в примере из реальных приложений.

Idsa комментирует...

По тегу Entity Framework можете найти и другие статьи из этого цикла. Хотя статьи не первой свежести, и уже потеряли свою значимость (какую-никакую).

qualarella комментирует...

Большое спасибо за материалы - все расписано достаточно грамотно :)

Александр комментирует...

Добавьте ссылки на следующие статьи :)

Idsa комментирует...

Александр, воспользуйтесь тегом "Entity Framework" ;)