Развитие Entity Framework
65Работа с базами данных в .NET Framework --- Entity Framework 6 --- Развитие Entity Framework
При работе с реляционными базами данных мы используем таблицы со строками и столбцами, такая инфраструктура устройства баз данных является очень структурированной. Перед широким внедрением объектно-ориентированного программирования мы работали в рамках “процедурного” программирования – для решения проблем использовался структурный код и функции. Устройство баз данных в виде таблиц, строк и столбцов было в какой-то степени похоже на структурные и процедурные шаблоны программирования, которые мы использовали в нашем коде. Жизнь была хороша ...
После этого произошла эволюция на стороне кода – сейчас мы уже не используем функции, а думаем в терминах объектов, классов и моделей. Процесс разработки программного обеспечения значительно повзрослел за эти годы и обрел концептуальный уровень – изменилось все, начиная от кода (появились ООП, различные фреймворки и шаблоны облегчающие жизнь) и заканчивая командами разработчиков (современный крупный проект трудно представить без архитекторов, дизайнеров, оптимизаторов и т.д.)
При этом эти изменения практически не затронули базы данных. Данные все также остаются заперты в таблицах, строках и столбцах. Это создает большую пропасть в работе между иерархическим объектно-ориентированным кодом и высоко-нормализованной структурой баз данных. Чтобы справиться с этой проблемой, разработчики предложили внести в программные проекты “объектный слой базы данных”, в котором таблицы баз данных представлялись в виде классов, столбцы в виде свойств, а вся работа с базой данных строилась на программном коде без использования SQL. Такой подход получил название объектно-реляционного отображения (object-relational mapping — ORM).
Различные программные платформы предлагают множество систем, реализующих модель ORM. Entity Framework в сочетании с LINQ (Language-Integrated Query) представляет собой реализацию ORM для платформы .NET Framework от компании Microsoft. Entity Framework содержит механизмы создания и работы с сущностями базы данных через объектно-ориентированный код на языке, совместимым с CLR (в наших примерах мы будем использовать C#). LINQ представляет собой библиотеку, расширяющую возможности C#, и облегчающую создание запросов (благодаря LINQ можно создавать SQL-подобные запросы в коде C#).
Entity Framework является продолжением другого API-интерфейса для работы с базами данных в .NET – ADO.NET, в котором для работы с базами данных приходилось писать запросы на SQL и вставлять их в команды. Думаю как вы поняли, Entity Framework значительно облегчает жизнь программистам C#, слабо разбирающимся в SQL и в деталях работы с базами данных.
История развития Entity Framework
Entity Framework представляет стратегический подход Microsoft к технологии доступа к данным для построения приложений. В отличие от предыдущих технологий доступа к данным, Entity Framework, в сочетании с Visual Studio, обеспечивает широкие возможности работы с базами данных и может использоваться в любых приложениях, будь это веб-сайт, настольное приложение или веб-служба. Давайте кратко рассмотрим хронологию развития Entity Framework.
Впервые Entity Framework появился в 2007 году, а его первая поддержка была обеспечена в Visual Studio 2008, после чего этот API-интерфейс проделал долгий путь и оброс новыми возможностями:
В первой версии Entity Framework был достаточно ограничен и обеспечивал только базовую реализацию модели ORM на основе подхода Database-First (рассмотрим чуть позже). Версия 4.0 появилась вместе с .NET Framework 4 и Visual Studio 2010 и принесла нам новый подход - Model-First и поддержку POCO-объектов (POCO - Plain Old CLR Object). Вскоре после этого, команда разработчиков Entity Framework выпустила три версии (4.1 – 4.3), в которых поддерживался еще один подход к реализации ORM – Code-First.
Версия 5 Entity Framework вышла вместе с выпуском .NET 4.5 и Visual Studio 2012. Эта версия обеспечивает значительное повышение производительности наряду с поддержкой перечислений, табличных функций, пространственных типов Transact SQL, импорта хранимых процедур, и глубокой интеграцией с ASP.NET MVC.
Текущей версией Entity Framework является 6, в которой появилась поддержка асинхронных запросов и возможность работы с хранимыми процедурами через подход Code-First. Более подробный список изменений в версиях Entity Framework вы можете увидеть на сайте MSDN в статье Entity Framework Version History.
Структура Entity Framework
Теперь давайте кратко рассмотрим некоторые ключевые моменты Entity Framework.
Модель EDM
Entity Framework акцентирует свое внимание на моделировании, в котором вы увидите много знакомых вещей – здесь используются диаграммы ER (entity-relationship, “сущность-отношение”), подход с использованием логического и физического проектирования слоев и многое другое. Ядром Entity Framework является модель EDM (Entity Data Model), суть которой заключается в хранении сущностей (entity) в виде строго типизированных классов, а не в виде объектов схемы базы данных (показано на рисунке ниже). Модель EDM позволяет обеспечить связь между сущностными классами в коде и таблицами базы данных.
Обратите внимание, что на рисунке выше, таблицы базы данных непосредственно не отображаются на классы сущностей, вместо этого у разработчика есть возможность управлять процессом отображения и он может, например, разбить таблицу на несколько сущностей или наоборот, объединить несколько таблиц в одной сущности (хотя зачастую программисты не используют эту возможность и используют отображение “1 таблица – 1 сущность”).
Слои
Архитектура Entity Framework в абстрактном смысле основана на слоях (layers): рабочий, удаленный и связующий.
Классы с кодом сущностей содержатся в рабочем слое, в котором работают программисты. В зависимости от того, какой подход вы используете (Code-First или DB-First), рабочий слой может быть смоделирован либо с помощью графического дизайнера Visual Studio, либо с помощью кода. После этого у программистов появляется широкий инструментарий для работы с Entity Framework. Синтаксис рабочего слоя описывается с помощью языка Conceptual Schema Definition Language (CSDL).
Удаленный слой определяет таблицы, столбцы, строки, отношения между таблицами базы данных. Синтаксис удаленного слоя описывается с помощью языка Store Schema Definition Language (SSDL).
Связующий слой определяет соответствие между рабочим и удаленным слоями, он связывает свойства сущностного класса в рабочем слое со столбцами таблицы базы данных в удаленном слое. Управлять этим слоем (т.е деталями привязки) можно из окна Mapping Details находящегося в инструментах дизайнера Visual Studio или с помощью аннотаций Fluent API, если вы работаете с подходом Code-First. Язык Mapping Specification Language (MSL) определяет синтаксис связующего слоя.
Важно отметить, что языки CSDL, SSDL и MSL имеют синтаксис XML, но при этом используют разную семантику.
Файлы Entity Framework
Все файлы, используемые в Entity Framework основаны на синтаксисе XML. Использование XML делает файлы простыми и универсальными для других приложений. Также XML-файлы читабельны для человека – вы можете в любой момент открыть и просмотреть содержимое этих файлов. Тем не менее, каждый элемент Entity Framework использует различные файлы XML с различным расширением.
После того как вы создадите новое приложение, которое опирается на Entity Framework и добавите сущностные классы базы данных, вы сможете увидеть результирующие файлы в основной папке проекта (в следующей статье мы более подробно опишем генерацию сущностных классов). В среде Visual Studio 2012 вы найдете единственный файл Entity Data Model XML (.EDMX), хотя в более старых версиях Visual Studio возможно будет создано несколько файлов (один для каждой сущности).
Файл EDMX содержит в себе несколько секций, написанных на языках CSDL, SSDL и MSL, представляющих разные слои в архитектуре Entity Framework. Чтобы открыть исходный код этого файла в Visual Studio, щелкните по нему правой кнопкой мыши и выберите в контекстном меню Open With…, после чего в диалоговом окне выберите вариант XML Editor.
Раздел CSDL содержит XML-код, необходимый для построения рабочего слоя:
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="SampleDbModel" ...>
<EntityType Name="Employee">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Int32" Nullable="false" />
<Property Name="FirstName" Type="String" MaxLength="20"
FixedLength="true" Unicode="true" Nullable="false" />
<Property Name="LastName" Type="String" MaxLength="20"
FixedLength="true" Unicode="true" Nullable="false" />
<Property Name="DepartamentNumber" Type="String" MaxLength="4"
FixedLength="true" Unicode="false" />
<NavigationProperty Name="Department"
Relationship="Self.FK_Employee_Department"
FromRole="Employee" ToRole="Department" />
<NavigationProperty Name="Works_on"
Relationship="Self.FK_Works_on_Employee"
FromRole="Employee" ToRole="Works_on" />
</EntityType>
<EntityContainer Name="SampleDbEntities" annotation:LazyLoadingEnabled="true">
<EntitySet Name="Department" EntityType="Self.Department" />
<EntitySet Name="Employee" EntityType="Self.Employee" />
<EntitySet Name="Project" EntityType="Self.Project" />
<EntitySet Name="sysdiagrams" EntityType="Self.sysdiagrams" />
<EntitySet Name="Works_on" EntityType="Self.Works_on" />
<AssociationSet Name="FK_Employee_Department" Association="Self.FK_Employee_Department">
<End Role="Department" EntitySet="Department" />
<End Role="Employee" EntitySet="Employee" />
</AssociationSet>
...
</EntityContainer>
</Schema>
</edmx:ConceptualModels>
Обратите внимание, что в CSDL описываются сгенерированные сущности и связи между ними в разделе EntityContainer. В элементах EntityType описывается структура сущностей – имена столбцов и первичные ключи. Обратите внимание на атрибут Type, в котором указывается тип сущности – в данном случае используются .NET-совместимые типы, а не типы T-SQL.
Секция с кодом SSDL описывает структуру таблиц базы данных, их структуру, хранимые процедуры и т.д. Разделы EntityContainer и EntityType аналогичны секции CSDL, но записи опираются на типы данных T-SQL, а не .NET. В примере ниже показана часть секции с кодом SSDL:
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="SampleDbModel.Store" ...>
<EntityType Name="Employee">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="int" Nullable="false" />
<Property Name="FirstName" Type="nchar" MaxLength="20" Nullable="false" />
<Property Name="LastName" Type="nchar" MaxLength="20" Nullable="false" />
<Property Name="DepartamentNumber" Type="char" MaxLength="4" />
</EntityType>
...
<EntityContainer Name="SampleDbModelStoreContainer">
<EntitySet Name="Employee" EntityType="Self.Employee" Schema="dbo" store:Type="Tables" />
...
<AssociationSet Name="FK_Employee_Department" Association="Self.FK_Employee_Department">
<End Role="Department" EntitySet="Department" />
<End Role="Employee" EntitySet="Employee" />
</AssociationSet>
...
</EntityContainer>
</Schema>
</edmx:StorageModels>
Код MDL связывает сущности, указанные в разделах SSDL и CSDL, и определяет как будут отображаться данные из базы данных на классы .NET. В примере ниже показана часть секции с кодом MDL:
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
<EntityContainerMapping ...>
<EntitySetMapping Name="Employee">
<EntityTypeMapping TypeName="SampleDbModel.Employee">
<MappingFragment StoreEntitySet="Employee">
<ScalarProperty Name="Id" ColumnName="Id" />
<ScalarProperty Name="FirstName" ColumnName="FirstName" />
<ScalarProperty Name="LastName" ColumnName="LastName" />
<ScalarProperty Name="DepartamentNumber" ColumnName="DepartamentNumber" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
...
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
Подходы для работы с Entity Framework
В Entity Framework поддерживается три подхода к разработке:
- Database-First
Подходит для проектировщиков баз данных - сначала вы создаете базу данных с помощью различных инструментов (например, SQL Server Management Studio), а затем генерируете EDMX-модель базы данных, которая предоставляет удобный графический интерфейс для взаимодействия с базой данных в виде диаграмм и объектную модель в виде классов C#. В данном случае вам нужно работать с SQL Server и хорошо знать синтаксис T-SQL, но при этом не нужно разбираться в C#.
- Model-First
Подходит для архитекторов - сначала вы создаете графическую модель EDMX в Visual Studio (в фоновом режиме создаются классы C# модели), а затем генерируете на основе диаграммы EDMX базу данных. При данном подходе не нужно знать ни деталей T-SQL ни синтаксиса C#.
- Code-First
Подходит для программистов - при данном подходе модель EDMX вообще не используется и вы вручную настраиваете классы C# объектной модели (данный подход поддерживает как генерацию сущностных классов из существующей базы данных, так и создание базы данных из созданной вручную модели объектов C#). Очевидно, что это подходит для программистов, хорошо знакомых с синтаксисом C#.
Позже мы рассмотрим каждый из этих подходов более подробно.