Сегодня я попытаюсь разобраться с шаблоном разработки Code First для Entity Framework, а так же что такое миграции и для чего они нужны. Речь пойдет о EF 5.0.
Code First позволяет определить модель данных на основе POCO-классов (Plain Old CLR Objects), а затем сопоставить эти классы с существующей или сгенерировать новую базу данных.
Что же, попробуем начать и будем разбираться по ходу дела. Создадим пустой Console Application. Реализуем простенький пример с сотрудниками. Поэтому создадим для начала класс Employee:
public class Employee
{
[StringLength(50)]
public int Id { get; set; }
public string FirstName { get; set; }
}
Так же добавим класс Department:
public class Department
{
public int Id { get; set; }
[StringLength(50)]
public string Name { get; set; }
public ICollection <Employee> Employees { get; set; }
}
Виды отношений между таблицами будут распознаны, для отношения типа 1:n в классе Department необходимо реализовать интерфейс ICollection<T> - где T является типом объекта в другой таблице связи, в данном случае Employee. Если же нужно отношение тип n:m, тогда необходимо интерфейс ICollection<T> реализовать в обоих классах.
По умолчанию свойство с именем Id или <class name>Id считается первичным ключом (регистр симвоолов при этом не учитывается), так же, начиная с EF 5.0, в качестве первичного ключа может использоваться Guid (в данном примере оставим int). Если же есть необходимость использовать другое имя для первичного ключа, то для это применяется атрибут Key.
Примечание: при использовании Guid в качестве первичного ключа его необходимо инициализировать в конструкторе
В приведенном выше коде я использовал атрибут [StringLength(int)], который задает максимальную длину строки, без использования данного атрибута будет применен тип nvarchar(max). Есть достаточно много атрибутов, которые облегчают жизнь, и которые будут применяться в этом примере, но я не хочу тратить время на их описание. Основные из них можно посмотреть тут.
Продолжаем!
Т.к. у нас пустое приложение, нам необходимо добавить ссылку на EF5 с помощью NuGet Packages, благодаря чему появятся все необходимые библиотеки:
Такого же эффекта можно добиться, используя Package Manager Console (TOOLS > Library Package Manager) совместно с командой Install-Package EntityFramework –Pre
Теперь добавим настройки подключения к БД. Для этого добавим в App.Config параметр <connectionStrings>:
<connectionStrings>
<add name="CodeContext" connectionString="Data Source=ServerName;
Initial Catalog=EFTest;Integrated Security=true;" providerName="System.Data.SqlClient"/>
</connectionStrings>
Далее создадим контекст базы данных, для чего необходимо создать производный от DbContext класс. Создадим файл CodeContext.cs и добавим следующий код:
namespace Employee.EF
{
public class CodeContext : DbContext
{
public CodeContext() : base("CodeContext")
{
}
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
}
}
Обратите внимание! Если имя connectionString совпадает с именем контекста (в данном случае это CodeContext и они совпадают), то DbContext распознает строку подключения к БД и все будет ОК. Если же имена разные, то необходимо для DbContext использовать это подключение путем указания имени подключения в конструкторе DbContext. Вообще, если не указывать настройки подключения, то DbContext использует имя производного класса контекста - Employee.EF.CodeContext, как имя базы данных и создает подключении используя SQL Express или LocalDb (устанволен по умолчанию в VisualStudio 2012). Если же установлены оба из них, то по умолчанию будет использоваться SQL Express.
Итак, давайте перейдем в наш programs.cs и добавим следующий код в класс Program:
static void Main(string[] args)
{
using (var ctx = new CodeContext())
{
ctx.Employees.Add(new Employee {FirstName = "Alex"});
ctx.SaveChanges();
var employees = ctx.Employees.ToList();
foreach (var employee in employees)
{
Console.WriteLine(employee.FirstName);
}
Console.ReadKey();
}
}
Теперь можно запустить наш код!
Нам вывелось содержимое таблицы Employees, следовательно наша база данных создалась автоматически:
Как видите, связь между таблицами создалась автоматически.
Теперь предлагаю внести некоторые изменения в какой-либо из наших классов, например, Employee:
public class Employee
{
public int Id { get; set; }
[StringLength(50)]
[Required]
public string FirstName { get; set; }
[StringLength(50)]
[Required]
public string SecondName { get; set; }
}
И добавим фамилию нашему сотруднику, т.к. у поля SecondName появился атрибут [Required], т.е. not null.
ctx.Employees.Add(new Employee {FirstName = "Alex", SecondName = "Tarasov"});
ctx.SaveChanges();
и попробуем скомпилировать код, в результате чего получим следующую ошибку:
как видно из сообщения - сейчас самое время подойти к вопросу миграции.
Отступление: Если на этапе разработки вы не работаете с большими объемами данных или эти данные вообще вам не важны, то можно применить следующий подход - добавим класс инициализатор:
class Init: DropCreateDatabaseIfModelChanges<CodeContext>
{
}
и пропишем инициализатор в program.cs:
Database.SetInitializer<CodeContext>(new Init());
Так может показаться, что все замечательно, если базы нет, то она создастся, если есть - удалится и создастся, НО будет хорошо только в том случае, если у вас нет множества данных в БД, а ведь работу над проектом может вести много разработчиков, что реально может привести к хаотичному пересозданию базы и потери каких-либо данных, пусть даже тестовых.
Короче говоря - МИГРАЦИИ БЫТЬ! Поэтому мы не будем при изменении модели пересоздавать БД.
Итак, миграция - это поддержка версионности базы данных.
Давайте посмотрим, что у нас есть сейчас
На данный момент нас интересует таблица MigrationHistory, в которой содержаться имя версии БД, время ее создания, так называемый слепок модели и версия EF. Эта таблица создается автоматически и не попадает в базу благодаря неведомому волшебству, даже без включенного механизма миграции. При использовании миграции мы можем с уверенностью сказать, что все изменения с базой будут попадать в эту таблицу и мы с можем всегда увидеть, в каком состоянии находится наша БД.
В следующей части этой статьи побробнее разберем пример с миграцией
Полезные ссылки:






Комментариев нет:
Отправить комментарий