В процессе разработки ПО, когда ещё не весь функционал определён окончательно, структура БД часто изменяется. И если используется какой-либо ORM-framework, изменение БД после изменения модели данных доставляет некоторые неудобства (по сути нужно проделать двойную работу по изменению класса модели и структуры БД). Вкратце, как сделать миграцию в EF4 Code First с помощью Package Manager Console описано здесь, я же постараюсь описать как работает автоматическая миграция без участия разработчика (точнее, при минимальном участии).
Встала задача создания нового проекта, представляющего из себя что-то вроде АРМа.
Посовещавшись, решили использовать Entity Framework Code First, т.к. в перспективе возможна смена СУБД, а с этим вариантом нам нужно будет просто сменить строку соединения (если имеется подходящий ADO.NET провайдер).
Сделали модели данных, класс контекста, наследуемый от DbContext'а:
добавили инициализатор:
и прописываем (в нашем случае в Global.asax) инициализатор:
Всё вроде замечательно, у кого базы нет она создаться, но после уточнения у заказчика деталей, возникла необходимость добавить ещё сущности. А так как разработку ведут несколько разработчиков, произошло массовое пересоздание БД, а данные там уже реальные лежали.
Так мы пришли к миграциям. Как советует статья выполнили в Package Manager Console команду:
В проекте появилась папка Migrations, в которой создалось два файла: Configuration.cs, <дата_время>_1.cs. Первый, как следует из названия конфигурация миграции, второй содержит необходимые изменения БД для обновления/отката версии. Далее достаточно выполнить в консоли NuGet'а:
Всё было замечательно, если у кого-то модель не совпадала с БД, он просто делал миграцию в консоли и удалял файлик с миграцией. Пока не пришло время разместить проект на сервере заказчика. NuGet'а там не было, и установить возможности тоже не было (а у хостинг-провайдера такая возможность, отсутствует в принципе, если не берёте сервер).
Пытаясь выяснить, как делать автоматическую миграцию, вооружившись IntelliSense,методом научного тыка эмпирическим методом выяснили, что нужно сменить класс, от которого наследуется инициализатор:
Запустили и получили такое исключение:

Ага! Делаем, то, что предлагается в сообщении исключения, то есть:
запускаем и видим, что миграция проходит автоматически.
Мы добились чего хотели, сейчас миграции проходят без участия разработчика, но я упоминал, что некоторое участие всё же понадобится, например если переименовать свойство модели и запустить проект, то мы увидим следующее исключение:

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

Ага! Делаем, то, что предлагается в сообщении исключения, то есть:
public sealed class Configuration : DbMigrationsConfiguration<ProjectContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(ProjectContext context)
{
}
}
запускаем и видим, что миграция проходит автоматически.
Мы добились чего хотели, сейчас миграции проходят без участия разработчика, но я упоминал, что некоторое участие всё же понадобится, например если переименовать свойство модели и запустить проект, то мы увидим следующее исключение:

Дело в том, что с точки зрения Entity Framework переименование свойства есть удаление и добавления с новым именем, а таким образом возможно потеря данных. В таких случаях (а их бывает немного), просто нужно создать миграцию вручную командой Add-Migration и поправить вручную DropColumn и CreateColumn на RenameColumn (или ещё что-то, в зависимости от ситуации).
Заключение
На этом всё, надеюсь статья будет полезной. А также надеюсь, что информации от первоисточника по данному вопросу очень мало, потому-что это как-бы бета-версия и с релизом Entity Framework 5.0, не придётся методом проб и ошибок искать правильный вариант использования.