Настройка подключения к базе данных
153Работа с базами данных в .NET Framework --- Entity Framework 6 --- Настройка подключения к базе данных
При работе с 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 автоматически найдет нужную строку подключения в файле конфигурации и использует ее. В примере ниже показано определение строки подключения:
<configuration>
...
<connectionStrings>
<add name="SampleContext" providerName="System.Data.SqlClient"
connectionString="Server=.\SQLEXPRESS;Database=MyShop2;Trusted_Connection=true"/>
</connectionStrings>
...
</configuration>
Запустите этот пример и убедитесь, что Code-First создаст новую базу данных с именем MyShop2 для текущей модели. Если вы прорабатывали примеры из предыдущих статей, то пока удалите вызов конструктора базового класса из класса контекста. В результате будет создана следующая база данных:
Настройка подключения в конструкторе класса контекста
Выше вы видели, как задать строку подключения из файла конфигурации так, что контекст будет использовать ее автоматически благодаря соглашениям Code-First. Теперь давайте посмотрим на некоторые способы управления подключением к базе данных из кода.
Класс DbContext помимо конструктора по умолчанию включает в себя несколько перегруженных версий конструкторов. Если вы используете один из этих конструкторов, Code-First не будет использовать соглашения для автоматического поиска строки подключения. Самая простая версия конструктора класса DbContext принимает один строковый параметр. Давайте посмотрим как использовать этот конструктор из производного класса:
public class SampleContext : DbContext
{
public SampleContext() : base("MyShop")
{ }
public DbSet<Customer> Customers { get; set; }
}
В этом конструкторе передается либо имя базы данных, либо полностью определенная строка подключения. Entity Framework достаточно интеллектуален, чтобы различить просто имя и строку подключения, в данном примере мы указываем имя базы данных.
Обратите внимание, что в этом примере мы вызываем перегруженный конструктор класса DbContext из конструктора по умолчанию производного класса SampleContext. При таком подходе к проектированию, когда вы создаете объект контекста в вашем приложении, строка подключения будет автоматически выбираться из конструктора по умолчанию класса SampleContext. Иногда бывает необходимо указать строку подключения при создании объекта контекста. Для этого можно добавить перегруженный конструктор в класс контекста с вызовом перегруженного конструктора DbContext:
public class SampleContext : DbContext
{
public SampleContext()
{ }
public SampleContext(string dbNameOrConnection)
: base(dbNameOrConnection)
{ }
// ...
}
Теперь в коде работы с данными, при создании объекта класса контекста вы можете указывать имя базы данных или строку подключения:
protected void Page_Load(object sender, EventArgs e)
{
SampleContext context = new SampleContext(
@"Server=.\SQLEXPRESS;Database=MyShop2;Trusted_Connection=true");
context.Customers.ToList();
}
В этом примере извлекаются данные всех покупателей из таблицы Customers базы данных MyShop2, т.к. мы указали полную строку подключения к этой базе данных. Если в данном примере вы создадите объект контекста с использованием конструктора по умолчанию:
SampleContext context = new SampleContext();
то Code-First использует соглашения по автоматическому поиску строки подключения, и, если не найдет строку подключения с именем SampleContext или CodeFirst.SampleContext, то попытается подключиться к базе данных с именем CodeFirst.SampleContext.
У вас также может возникнуть вопрос, как явно передать конструктору класса контекста имя строки подключения, если оно не соответствует имени класса контекста. Для этого можно использовать укороченную строку подключения с единственным параметром name:
public class SampleContext : DbContext
{
public SampleContext() : base("name=MyConnectionStringName")
{ }
// ...
}
Теперь Code-First будет искать в конфигурационном файле строку подключения с именем MyConnectionStringName.
Повторное использование подключения к базе данных
Одна из перегруженных версий конструктора DbContext принимает объект подключения DbConnection из пространства имен System.Data.Common. Использование этого объекта может быть полезно, если вы хотите указать в нескольких объектах контекста один и тот же объект подключения и не хотите каждый раз указывать имя базы данных или строки подключения. Т.е. объект DbConnection может храниться в определенном месте приложения и вы можете ссылаться на него всякий раз, когда создаете объект контекста. Ниже показан пример:
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.Data.Common;
namespace CodeFirst
{
// Определяет строку подключения к бд MyShop
public class DbConnectionToMyShop : DbConnection
{
public DbConnectionToMyShop()
{
this.ConnectionString = "...";
}
}
public class SampleContext : DbContext
{
public SampleContext() :
base(new DbConnectionToMyShop(), contextOwnsConnection: false)
{ }
public SampleContext(DbConnection connection) :
base(connection, false)
{ }
// ...
}
}
В этом примере мы создали класс 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:
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.Infrastructure;
namespace CodeFirst
{
// Класс конфигурации
public class MyDbConfig : DbConfiguration
{
public MyDbConfig()
{
SqlConnectionFactory defaultFactory =
new SqlConnectionFactory("Server=MyDbServer;User=username;Password=12345;");
this.SetDefaultConnectionFactory(defaultFactory);
}
}
[DbConfigurationType(typeof(MyDbConfig))]
public class SampleContext : DbContext
{
public SampleContext() : base("MyShop")
{ }
// ...
}
}
В этом примере мы изменяем имя сервера, а также указываем, что для доступа к серверу должна использоваться SQL-аутентификация, на основе имени пользователя и пароля. Обратите внимание, чтобы указать классу контекста, чтобы он использовал эту конфигурацию, используется атрибут DbConfigurationType. Чтобы зарегистрировать новый класс конфигурации, в файле Web.config веб-приложения нужно удалить раздел defaultConnectionFactory:
<entityFramework>
<!--<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />-->
...
</entityFramework>
Также вы можете установить конфигурацию для всех классов контекста в приложении и не использовать атрибут DbConfigurationType. Для этого укажите свойство codeConfigurationType раздела конфигурации entityFramework:
<entityFramework codeConfigurationType="CodeFirst.MyDbConfig, CodeFirst">
...
</entityFramework>
Здесь указывается ссылка на класс конфигурации и имя сборки, где этот класс располагается. Для настройки поставщика базы данных вы можете использовать метод SetProviderServices() класса конфигурации или использовать элементы provider разделе entityFramework файла конфигурации:
public class MyDbConfig : DbConfiguration
{
public MyDbConfig()
{
// ...
this.SetProviderServices("System.Data.SqlClient",
System.Data.Entity.SqlServer.SqlProviderServices.Instance);
}
}
<entityFramework codeConfigurationType="CodeFirst.MyDbConfig, CodeFirst">
<providers>
<provider invariantName="System.Data.SqlClient"
type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
В примерах выше показано использование стандартного поставщика данных SQL Server, но вы можете указать другие поставщики баз данных, которые требуются в вашем приложении (MySQL, Oracle и т.п.)