Ignore pending migrations after database recreation

佐手、 提交于 2019-12-11 03:07:42

问题


We am using code first EF 4.3.1 with database migrations. Sometimes we drop the database and let EF recreate it, mainly for local development purposes.

There is a procedure which applies pending migrations and when the database is recreated the pending migrations aren't necessary and error is thrown when EF tries to apply them.

I check the migration date from the string and if this is before the database creation date then I manually add it to the __migrationHistory table and don't apply the migration.

This covers most of the scenarios except when someone recreates the database, updates from source control and retrieves oustanding migrations which are before the database creation date.

I have also tried using a try catch around the dbMigrator.Update(migration) method call but if one migrations fails, further ones won't be applied as it remembers the exceptions.

Has anyone found a way to get around this issue?

This is the method I have written:

private static void ApplyMigration<T, TU>()
where T : DbContext, new()
where TU : DbMigrationsConfiguration, new()
{
    var migrationsAlreadyApplied = new List<string>();
    var dbMigrator = new DbMigrator(new TU());

    var creationMigrationId = dbMigrator.GetDatabaseMigrations().Single(m => m.Contains("InitialCreate"));
    var dbDateCreated = DateTime.ParseExact(creationMigrationId.Substring(0, 12), Constants.MigrationDateFormat, CultureInfo.InvariantCulture);

    dbMigrator.GetPendingMigrations().ToList()
                                    .ForEach(migration =>
                                    {
                                        var migrationDate = DateTime.ParseExact(migration.Substring(0, 12), Constants.MigrationDateFormat, CultureInfo.InvariantCulture);

                                        if (migrationDate > dbDateCreated)
                                            dbMigrator.Update(migration);
                                        else
                                            migrationsAlreadyApplied.Add(migration);
                                    });

    using (var dbContext = new T())
    {
        foreach(var migration in migrationsAlreadyApplied)
            dbContext.Database.ExecuteSqlCommand("insert into __MigrationHistory "
                      + "select '" + migration + "', Model, ProductVersion "
                      + "from __MigrationHistory "
                      + "where MigrationId = '" + migration + "'");
    }
}

回答1:


I have now resolved this.

In the seed method of my dbContext initialiser, I call a method which will populate the migration history manually. You can then use the ApplyMigrations method to call the migrations normally.

public class UserEntitiesContextInitializer : CreateDatabaseIfNotExists<UserEntitiesContext>
{
    protected override void Seed(UserEntitiesContext context)
    {
        // Update migration history with existing migrations to prevent EF recognising them as pending migrations
        DatabaseAdministration.UpdateMigrationHistory<UserEntitiesContext, UserEntitiesContextConfiguration>();
    }
}

public static void UpdateMigrationHistory<T, TU>()
        where T : DbContext, new()
        where TU : DbMigrationsConfiguration, new()
    {
        using (var dbContext = new T())
        {
            var dbMigrator = new DbMigrator(new TU());

            var creationMigrationId = dbMigrator.GetDatabaseMigrations().Single(m => m.Contains("InitialCreate"));

            foreach (var migration in dbMigrator.GetPendingMigrations())
                dbContext.Database.ExecuteSqlCommand("insert into __MigrationHistory "
                                                        + "select '" + migration + "', Model, ProductVersion "
                                                        + "from __MigrationHistory "
                                                        + "where MigrationId = '" + creationMigrationId + "'");
        }
    }

private static void ApplyMigration<T, TU>()
        where T : DbContext, new()
        where TU : DbMigrationsConfiguration, new()
    {
        var dbMigrator = new DbMigrator(new TU());

        if (dbMigrator.GetPendingMigrations().Any())
            dbMigrator.Update(dbMigrator.GetPendingMigrations().Last());
    }


来源:https://stackoverflow.com/questions/13155292/ignore-pending-migrations-after-database-recreation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!