В процессе разработки ПО, когда ещё не весь функционал определён окончательно, структура БД часто изменяется. И если используется какой-либо ORM-framework, изменение БД после изменения модели данных доставляет некоторые неудобства (по сути нужно проделать двойную работу по изменению класса модели и структуры БД). Вкратце, как сделать миграцию в EF4 Code First с помощью Package Manager Console описано здесь, я же постараюсь описать как работает автоматическая миграция без участия разработчика (точнее, при минимальном участии).
С чего всё началось
Встала задача создания нового проекта, представляющего из себя что-то вроде АРМа.
Посовещавшись, решили использовать Entity Framework Code First, т.к. в перспективе возможна смена СУБД, а с этим вариантом нам нужно будет просто сменить строку соединения (если имеется подходящий ADO.NET провайдер).
Сделали модели данных, класс контекста, наследуемый от DbContext'а:
public class ProjectContex : DbContext
{
public ProjectContex()
{
}
public ProjectContex(string connString)
: base(connString)
{
}
public DbSet<Address> Addresses { get; set; }
...
}
добавили инициализатор:
public class ProjectInitializer : DropCreateDatabaseIfModelChanges<ProjectContex>
{
protected override void Seed(VaccinationContex context)
{
...
}
}
Всё вроде замечательно, у кого базы нет она создаться, но после уточнения у заказчика деталей, возникла необходимость добавить ещё сущности. А так как разработку ведут несколько разработчиков, произошло массовое пересоздание БД, а данные там уже реальные лежали.
Миграции
Так мы пришли к миграциям. Как советует статья выполнили в Package Manager Console команду:
PM> Add-Migration 1
В проекте появилась папка Migrations, в которой создалось два файла: Configuration.cs, <дата_время>_1.cs. Первый, как следует из названия конфигурация миграции, второй содержит необходимые изменения БД для обновления/отката версии. Далее достаточно выполнить в консоли NuGet'а:
PM> Update-Database
Всё было замечательно, если у кого-то модель не совпадала с БД, он просто делал миграцию в консоли и удалял файлик с миграцией. Пока не пришло время разместить проект на сервере заказчика. NuGet'а там не было, и установить возможности тоже не было (а у
Автоматическая миграция
Пытаясь выяснить, как делать автоматическую миграцию, вооружившись IntelliSense, методом научного тыка эмпирическим методом выяснили, что нужно сменить класс, от которого наследуется инициализатор:
//public class ProjectInitializer : DropCreateDatabaseIfModelChanges<ProjectContex>
public class ProjectInitializer : MigrateDatabaseToLatestVersion<ProjectContex, Configuration>
{
...
}
Запустили и получили такое исключение:
Ага! Делаем, то, что предлагается в сообщении исключения, то есть:
public sealed class Configuration : DbMigrationsConfiguration<OCode.Vaccine.DataAccessObjects.Model.VaccinationContex>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(OCode.Vaccine.DataAccessObjects.Model.VaccinationContex context)
{
}
}
запускаем и видим, что миграция проходит автоматически.
Мы добились чего хотели, сейчас миграции проходят без участия разработчика, но я упоминал, что некоторое участие всё же понадобится, например если переименовать свойство модели и запустить проект, то мы увидим следующее исключение:
Дело в том, что с точки зрения Entity Framework переименование свойства есть удаление и добавления с новым именем, а таким образом возможно потеря данных. В таких случаях (а их бывает немного), просто нужно создать миграцию вручную командой Add-Migration и поправить вручную DropColumn и CreateColumn на RenameColumn (или ещё что-то, в зависимости от ситуации).
Заключение
На этом всё, надеюсь статья будет полезной. А также надеюсь, что информации от первоисточника по данному вопросу очень мало, потому-что это как-бы бета-версия и с релизом Entity Framework 5.0, не придётся методом проб и ошибок искать правильный вариант использования.
Автор: CyberCoder