Entity Framework, автоматическое применение миграции

Я использую Entity Framework Code First с помощью AutomaticMigrationsEnabled = true:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbContext, MigrateDBConfiguration>());
//////////////////////////////////

public class MigrateDBConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<DbContext>
{
    public MigrateDBConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }
}

При первом запуске проекта создается база данных и таблицы, как и ожидалось. После изменения моей модели путем добавления или удаления полей я запустил Add-Migration. Класс Migration создан, но после запуска проекта возникает исключение:

Исключение типа "System.InvalidOperationException" возникло в EntityFramework.dll, но не было обработано в коде пользователя

Дополнительная информация: модель, поддерживающая контекст DBContext, имеет изменено с момента создания базы данных.

ОБНОВЛЕНИЕ: В соответствии с указаниями в ответе arturo menchaca я изменил свой код следующим образом:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<DBContext, MigrateDBConfiguration<DBContext>>());

...

После изменения возникает исключение:

В базе данных уже есть объект с именем "MyTable".

Как я могу применить миграцию моей базы данных?

Ответ 1

Наконец, я нашел решение своей проблемы. Я вызываю этот метод в каждом запуске приложения:

public void InitializeDatabase(DataAccessManager context)
{
    if (!context.Database.Exists() || !context.Database.CompatibleWithModel(false))
    {
        var configuration = new DbMigrationsConfiguration();
        var migrator = new DbMigrator(configuration);
        migrator.Configuration.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString, "System.Data.SqlClient");
        var migrations = migrator.GetPendingMigrations();
        if (migrations.Any())
        {
            var scriptor = new MigratorScriptingDecorator(migrator);
            var script = scriptor.ScriptUpdate(null, migrations.Last());

            if (!string.IsNullOrEmpty(script))
            {
                context.Database.ExecuteSqlCommand(script);
            }
        }
    }
}

Ответ 2

Автоматическая миграция означает, что вам не нужно запускать команду add-migration для ваших изменений в моделях, но вам нужно запустить команду update-database вручную.

Если автоматическая миграция включена, когда вы вызываете update-database, если в моделях ожидаются изменения, будет добавлена ​​ "автоматическая" миграция, и база данных будет обновлена.

Если вы хотите, чтобы ваша база данных обновлялась без необходимости вызова команды update-database, вы можете добавить метод Database.SetInitializer(...) в OnModelCreating() в свой контекст, например:

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, MigrateDBConfiguration>());
    }

    ...
}

public class MigrateDBConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<MyContext>
{
    ...

Обратите внимание, что вы должны объявлять DbMigrationsConfiguration и MigrateDatabaseToLatestVersion своим реальным контекстом, а не по умолчанию DbContext.

Ответ 3

Если у вас есть изменения в ваших сущностях, сначала нужно запустить add-migration, чтобы создать миграцию script.

После этого в Global.asax

вам нужно иметь такой код, как этот

        var configuration = new MyProject.Configuration();
        var migrator = new System.Data.Entity.Migrations.DbMigrator(configuration);            

        migrator.Update();

каждый раз, когда вы запускаете проект asp.net, он проверяет, есть ли у вас новая миграция для запуска и запускайте update-database автоматически для вас.