Автоматическая миграция БД в Entity Framework

в 10:28, , рубрики: .net, .net 4.0, orm, метки: ,

В процессе разработки ПО, когда ещё не весь функционал определён окончательно, структура БД часто изменяется. И если используется какой-либо 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>
{
     ...
}

Запустили и получили такое исключение:

Автоматическая миграция БД в Entity Framework

Ага! Делаем, то, что предлагается в сообщении исключения, то есть:

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

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

Заключение

На этом всё, надеюсь статья будет полезной. А также надеюсь, что информации от первоисточника по данному вопросу очень мало, потому-что это как-бы бета-версия и с релизом Entity Framework 5.0, не придётся методом проб и ошибок искать правильный вариант использования.

Автор: CyberCoder

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js