- Настройка подключения к базе данных
- Использование конфигурационного файла приложения
- Настройка подключения в конструкторе класса контекста
- Повторное использование подключения к базе данных
- Настройка соглашений подключения в Code-First
- Подходы для работы с Entity Framework
- Подход Code-First
- Подход Model-First
- Подход Database-First
- Совместимые с Entity Framework поставщики данных
- Как выбрать нужный подход?
Настройка подключения к базе данных
При работе с Entity Framework во всех предыдущих примерах мы полагались на соглашения Code-First по автоматическому определению подключения к базе данных. По умолчанию, Code-First создает базу данных на локальном сервере .\SQLEXPRESS, используя полное имя класса контекста для имени базы данных (например, пространство имен + имя класса). Для примера нашего проекта это означает, что Code-First создаст базу данных с именем CodeFirst.SampleContext. Зачастую это поведение необходимо переопределить, в частности мы передавали имя базы данных MyShop в конструкторе класса контекста. В этой статье содержится подробное описание настроек имени базы данных и подключения к ней.
Использование конфигурационного файла приложения
Самым простым способом управления подключением к базе данных является использование конфигурационного файла приложения. В файле конфигурации можно переопределить базовые соглашения Code-First и точно указать строку подключения к базе данных. Этот подход особенно полезен, если вы хотите изменить строку подключения в вашем контексте, чтобы указать подключение к удаленной (не локальной) базе данных при развертывании приложения.
В приложениях ASP.NET конфигурационным файлом является файл Web.config, в приложениях другого типа – App.config. При использовании нескольких проектов в одном решении можно допустить ошибку с правильным выбором конфигурационного файла. Например, в нашем приложении сущностная модель находится в проекте библиотеки классов CodeFirst, а непосредственно с данными мы работаем в проекте веб-приложения ASP.NET. Возможно вам покажется правильным, разместить настройки подключения в файле App.config проекта CodeFirst. Однако это является неправильным решением. Entity Framework настраивает базу данных при создании объекта контекста, а не при его объявлении. В примерах, приводившихся ранее, мы использовали объект контекста в коде веб-форм, поэтому настройки строки подключения нужно указывать в файле Web.config веб-приложения ASP.NET.
Благодаря такому подходу обеспечивается возможность многоразового использования модели данных. В каждом проекте, где мы ссылаемся на проект CodeFirst, мы можем указать свою строку подключения, т.е. одна модель будет работать с разными базами данных.
Для указания строки подключения используется раздел конфигурации connectionString. По умолчанию, строка подключения должна иметь то же имя, что и файл контекста, при этом можно указать как полное имя так и краткое (т.е SampleContext или CodeFirst.SampleContext). Благодаря этому, Entity Framework автоматически найдет нужную строку подключения в файле конфигурации и использует ее. В примере ниже показано определение строки подключения:
Запустите этот пример и убедитесь, что Code-First создаст новую базу данных с именем MyShop2 для текущей модели. Если вы прорабатывали примеры из предыдущих статей, то пока удалите вызов конструктора базового класса из класса контекста. В результате будет создана следующая база данных:
Настройка подключения в конструкторе класса контекста
Выше вы видели, как задать строку подключения из файла конфигурации так, что контекст будет использовать ее автоматически благодаря соглашениям Code-First. Теперь давайте посмотрим на некоторые способы управления подключением к базе данных из кода.
Класс DbContext помимо конструктора по умолчанию включает в себя несколько перегруженных версий конструкторов. Если вы используете один из этих конструкторов, Code-First не будет использовать соглашения для автоматического поиска строки подключения. Самая простая версия конструктора класса DbContext принимает один строковый параметр. Давайте посмотрим как использовать этот конструктор из производного класса:
В этом конструкторе передается либо имя базы данных, либо полностью определенная строка подключения. Entity Framework достаточно интеллектуален, чтобы различить просто имя и строку подключения, в данном примере мы указываем имя базы данных.
Обратите внимание, что в этом примере мы вызываем перегруженный конструктор класса DbContext из конструктора по умолчанию производного класса SampleContext. При таком подходе к проектированию, когда вы создаете объект контекста в вашем приложении, строка подключения будет автоматически выбираться из конструктора по умолчанию класса SampleContext. Иногда бывает необходимо указать строку подключения при создании объекта контекста. Для этого можно добавить перегруженный конструктор в класс контекста с вызовом перегруженного конструктора DbContext:
Теперь в коде работы с данными, при создании объекта класса контекста вы можете указывать имя базы данных или строку подключения:
В этом примере извлекаются данные всех покупателей из таблицы Customers базы данных MyShop2, т.к. мы указали полную строку подключения к этой базе данных. Если в данном примере вы создадите объект контекста с использованием конструктора по умолчанию:
то Code-First использует соглашения по автоматическому поиску строки подключения, и, если не найдет строку подключения с именем SampleContext или CodeFirst.SampleContext, то попытается подключиться к базе данных с именем CodeFirst.SampleContext.
У вас также может возникнуть вопрос, как явно передать конструктору класса контекста имя строки подключения, если оно не соответствует имени класса контекста. Для этого можно использовать укороченную строку подключения с единственным параметром name:
Теперь Code-First будет искать в конфигурационном файле строку подключения с именем MyConnectionStringName.
Повторное использование подключения к базе данных
Одна из перегруженных версий конструктора DbContext принимает объект подключения DbConnection из пространства имен System.Data.Common. Использование этого объекта может быть полезно, если вы хотите указать в нескольких объектах контекста один и тот же объект подключения и не хотите каждый раз указывать имя базы данных или строки подключения. Т.е. объект DbConnection может храниться в определенном месте приложения и вы можете ссылаться на него всякий раз, когда создаете объект контекста. Ниже показан пример:
В этом примере мы создали класс DbConnectionToMyShop, для подключения к базе данных MyShop. Объект этого класса передается в конструкторе по умолчанию класса контекста. Мы также создали для удобства перегруженный конструктор — в коде приложения вы можете просто передать нужный объект подключения. Классы подключений можно определить в одном файле и затем использовать повсеместно в приложении. Второй параметр в этом конструкторе contextOwnsConnection указывает, нужно ли очищать объект подключения при удалении объекта контекста.
Настройка соглашений подключения в Code-First
Последним способом управления подключением к базе данных, является замена соглашений, которые использует Code-First. Соглашения по конфигурации подключения определяются с помощью интерфейса IDbConnectionFactory. Вы можете реализовать этот интерфейс и передать его методу SetDefaultConnectionFactory() класса DbConfiguration, переопределив тем самым соглашения по умолчанию Code-First.
Соглашения по умолчанию реализует класс SqlConnectionFactory из пространства имен System.Data.Entity.Infrastructure. Поведение по умолчанию определяет, что поставщиком базы данных будет поставщик SQL Server (сборка System.Data.SqlClient), имя сервера — .\SQLEXPRESS, а для доступа к серверу используется Windows-аутентификация (сервер доступен для текущего пользователя системы). Вы можете переопределить данные соглашения, например, для того, чтобы явно указать Entity Framework что вы хотите работать с поставщиком MySQL.
В примере ниже показано, как переопределить эти соглашения, используя класс конфигурации, унаследованный от DbConfiguration:
В этом примере мы изменяем имя сервера, а также указываем, что для доступа к серверу должна использоваться SQL-аутентификация, на основе имени пользователя и пароля. Обратите внимание, чтобы указать классу контекста, чтобы он использовал эту конфигурацию, используется атрибут DbConfigurationType. Чтобы зарегистрировать новый класс конфигурации, в файле Web.config веб-приложения нужно удалить раздел defaultConnectionFactory:
Также вы можете установить конфигурацию для всех классов контекста в приложении и не использовать атрибут DbConfigurationType. Для этого укажите свойство codeConfigurationType раздела конфигурации entityFramework:
Здесь указывается ссылка на класс конфигурации и имя сборки, где этот класс располагается. Для настройки поставщика базы данных вы можете использовать метод SetProviderServices() класса конфигурации или использовать элементы provider разделе entityFramework файла конфигурации:
В примерах выше показано использование стандартного поставщика данных SQL Server, но вы можете указать другие поставщики баз данных, которые требуются в вашем приложении (MySQL, Oracle и т.п.)
Подходы для работы с Entity Framework
При использовании Entity Framework в приложении существует три подхода для организации взаимодействия Entity Framework с базой данных: Code-First, Model-First и Database-First. В этой статье мы кратко рассмотрим эти подходы и проведем их сравнительный анализ, а более подробное описание каждого из подходов с использованием примеров будет приведено в следующих статьях.
Подход Code-First
, который впервые появился в Entity Framework 4.1, обычно используется, когда у вас есть уже существующее приложение, содержащее модель данных. Эта модель, как правило, описывается с помощью нескольких классов и кода взаимодействия между этими классами. Например, вы можете создать класс по имени Customer, который будет содержать данные покупателя в интернет-магазине:
Вы можете использовать этот класс модели в своем приложении без создания базы данных. Добавив дополнительный код, вы могли бы хранить объекты этого класса, например, на диске в формате XML или в памяти рабочего процесса программы. Однако когда ваше приложение расширяется и становится крупным, эти данные необходимо будет хранить в базе данных. Эта та точка, в которой и начинает работать подход Code-First – вы можете использовать существующий код для создания базы данных не беспокоясь о деталях реализации базы данных (этим займется Entity Framework), а вы можете сфокусировать свое внимание на коде.
Важно отметить, что класс, представляющий модель данных, должен иметь поле Id, которое будет использоваться в таблице базы данных в качестве первичного ключа. Entity Framework автоматически находит такое поле с помощью механизма рефлексии (в его имени должна содержаться строка “Id”, поэтому поле CustomerId в примере выше будет автоматически использоваться в качестве первичного ключа.) Это ограничение можно обойти, использовав свойство с произвольным именем и помеченное специальными атрибутами метаданных C#, которые используются в Entity Framework. Здесь мы их описывать не будем, я лишь заострил свое внимание на этом моменте, потому что он показывает, что любые настройки первичных и внешних ключей, ограничения между таблицами и т.д. при подходе Code-First указываются в модели (т.е. в управляемом коде C#), а потом проецируются на базу данных.
Подход Code-First появился позже подходов Model-First и Database-First и, как вы уже поняли, больше всего подходит для разработчиков, которые хотят писать код, а не работать с дизайнером модели EDM или средствами работы с базами данных (SQL Server Management Studio и T-SQL). Вы можете создать модель для вашего приложения, используя объекты CLR (Common Language Runtime) и специальные объекты POCO (Plain Old CLR Object).
При проектировании приложений с подходом Code-First, вы сначала создаете классы модели данных не обращая никакого внимания на Entity Framework. После того, как вам понадобилось работать с базой данных, вы используете различные инструменты, которые проецируют структуру базы данных из созданной модели классов. После этого вы можете вернуться к этой модели в коде и, например, изменить ее. Эти изменения затем можно будет отразить в базе данных используя все те же инструменты.
Важным нововведением версии Entity Framework 5 в плане подхода Code-First, является то, что созданная модель классов теперь сразу является сущностной моделью данных EDM (Entity Data Model), поэтому отпала необходимость использовать файл EDMX. В более ранних версиях разработчику, использующему подход Code-First, приходилось добавлять отношения между моделью классов и файлом EDMX, т.е. отображать любые изменения модели сразу в двух местах. Очевидно, что этот подход приводил к появлению кучи ошибок, если разработчик забывал синхронизировать эти изменения в обоих файлах.
Чтобы указать среде Visual Studio, что модель классов является моделью EDM, нужно во-первых установить сборки Entity Framework в проект, а во-вторых добавить класс контекста базы данных, унаследованный от класса DbContext, находящегося в пространстве имен System.Data.Entity, как показано в примере ниже (установку Entity Framework и настройку класса контекста мы более подробно будем рассматривать позже):
Вам не нужно беспокоится о способах взаимодействия с базой данных, Entity Framework определяет ряд вспомогательных методов. Вам не нужно знать деталей подключения и даже имени базы данных. Ниже показан пример вставки данных в таблицу с использованием тестового класса Customer, показанного выше:
Этот код является немного упрощенным, но все же показывает суть работы с Entity Framework. Конечно, вы можете глубже контролировать каждую операцию с базой данных. Этот пример использует максимальную автоматизацию и дает приемлемые результаты, по крайней мере в небольшом приложении. В последующих статьях мы рассмотрим более подробно настройки подхода Code-First, которые можно использовать для удовлетворения конкретных потребностей.
Подход Model-First
, впервые появившийся в версии Entity Framework 4, применяется разработчиками, которые не хотят использовать инструменты СУБД для создания и управления базами данных, а также не хотят вручную настраивать классы модели EDM. Фактически это самый простой подход при работе с Entity Framework. Проектирование модели происходит в графическом дизайнере EDM среды Visual Studio. Вы могли наблюдать использование Model-First в предыдущей статье, где мы создали простое приложение ASP.NET.
Рабочий процесс создания модели при подходе Model-First начинается в тот момент, когда вы проектируете базу данных. При этом вам необходимы минимальные знания устройства баз данных, например, для настройки отношений между таблицами в графическом дизайнере или указания типов данных SQL полей таблицы.
Как и в случае подхода Code-First, вся работа строится вокруг класса контекста базы данных. Фактически, взаимодействие с базой данных в этих подходах одинаковое. Например, для вставки объекта, используется следующая последовательность действий:
Создать объект модели и наполнить его данными.
Создать класс контекста, унаследованный от DbContext (в подходе Code-First это делается вручную, в Model-First этот класс генерируется автоматически вместе с сущностными классами).
Добавить объект в базу данных, используя класс контекста.
Подход Database-First
, появившийся вместе c Entity Framework, позволяет писать приложения для существующих баз данных. Базы данных в реальных приложениях довольно быстро становятся сложными и пытаться создать модель для существующей базы данных, которую могут понять разработчики, довольно трудно. Еще тяжелее написать код использования модели, в котором происходит взаимодействие с базой данных. Во многих отношениях, подход Database-First является противоположностью подходу Model-First. При подходе Database-First база данных уже существует, поэтому разработчик должен знать, где расположена база данных, а также иметь информацию об имени базы данных. Тем не менее, разработчик не должен понимать внутреннюю работу базы данных — Entity Framework по-прежнему скрывает внутреннюю реализацию из поля зрения.
При этом подходе, рабочий процесс создания модели начинается с создания и проектирования базы данных. После генерации сущностных классов модели из существующей базы данных, работа с Entity Framework аналогична подходам Code-First и Model-First. Это означает создание объекта класса контекста и использование этого объекта для выполнения необходимых задач.
Совместимые с Entity Framework поставщики данных
Для того, чтобы получить доступ к базе данных с помощью Entity Framework, нужно использовать поставщики данных, совместимые с Entity Framework. организуют взаимодействие между сущностными классами и системой управления базами данных (СУБД). Фактически они отвечают за то, например, какой код C# нужно сгенерировать из базы данных при использовании подхода Database-First, или какой код SQL нужно создать, при отображении графической модели EDMX на базу данных.
Visual Studio по умолчанию поставляется поставщиком данных SqlClient, что позволяет получить доступ к большинству версий СУБД SQL Server: 2005, 2008, 2010, 2012, 2014. Начиная с версии Visual Studio 2010, Microsoft отказалась от поддержки SQL Server 2000. Можно также создать приложение, обращающееся к SQL Server Compact. Тем не менее, этот провайдер имеет некоторые строгие ограничения, такие как неспособность поддерживать схемы с одинаковыми именами ограничений.
Вы также можете получить доступ к ряду сторонних поставщиков данных для других СУБД. В настоящее время поставщики данных Entity Framework поддерживаются следующими СУБД: MySQL, Oracle, Progress, VistaDB, Devart, OpenLink, SQL Anywhere, Sybase, SQLite, Synergex, Firebird и PostgreSQL (через поставщик Npgsql).
В списке провайдеров отсутствует поддержка базы данных Access Microsoft. Также Entity Framework не поддерживает старые технологии и методы доступа, такие как Open Database Connectivity (ODBC). Для того, чтобы получить поддержку Entity Framework для конкретной базы данных, вы можете создать EF-совместимый провайдер для нее. Более подробно об этом можно прочитать в статье «EF5 Sample Provider».
Как выбрать нужный подход?
Данный вопрос задает себе каждый разработчик, который планирует работать с Entity Framework. В данном случае можно посоветовать придерживаться целей каждого из подходов. Например, если вы запускаете приложение с нуля и у вас нет базы данных, то удобнее использовать подход Model-First. Если база данных есть, то можно использовать Database-First. Если нужно добавить поддержку Entity Framework в уже существующее приложение, где определена модель данных, логичнее всего использовать подход Code-First.
Однако, можно посоветовать использовать подход, удобный для разработчика. Очевидно, что подход Database-First удобен для разработчиков, которые хорошо разбираются в проектировании баз данных и знают основы T-SQL, т.к. этот подход подразумевает создание базы данных вручную. Model-First больше подходит для архитекторов приложений, т.к. использует удобную графическую среду и абстрагируется от реализации базы данных и создания классов модели. Code-First более удобен для программистов C#, т.к. позволяет настраивать детали базы данных из кода.
В следующей таблице показана сводка различных подходов для работы с Entity Framework:
Использование БД | Ориентация подхода | Подход | Описание |
---|---|---|---|
Новая БД | На графическую модель | Model-First | |
Существующая БД | На графическую модель | Database-First | |
Существующая БД | На код | Code-First (Code-Second) |