C# 忽略数据库重新创建后挂起的迁移

C# 忽略数据库重新创建后挂起的迁移,c#,.net,entity-framework,ef-code-first,entity-framework-migrations,C#,.net,Entity Framework,Ef Code First,Entity Framework Migrations,我们在数据库迁移中使用CodeFirstEF4.3.1。有时我们删除数据库并让EF重新创建它,主要是为了本地开发目的 有一个过程可以应用挂起的迁移,当重新创建数据库时,不需要挂起的迁移,当EF尝试应用它们时会抛出错误 我从字符串中检查迁移日期,如果该日期早于数据库创建日期,则手动将其添加到uu migrationHistory表中,并且不应用迁移 这涵盖了大多数情况,但有人重新创建数据库、从源代码管理进行更新以及检索数据库创建日期之前的未完成迁移时除外 我还尝试在dbMigrator.Updat

我们在数据库迁移中使用CodeFirstEF4.3.1。有时我们删除数据库并让EF重新创建它,主要是为了本地开发目的

有一个过程可以应用挂起的迁移,当重新创建数据库时,不需要挂起的迁移,当EF尝试应用它们时会抛出错误

我从字符串中检查迁移日期,如果该日期早于数据库创建日期,则手动将其添加到uu migrationHistory表中,并且不应用迁移

这涵盖了大多数情况,但有人重新创建数据库、从源代码管理进行更新以及检索数据库创建日期之前的未完成迁移时除外

我还尝试在dbMigrator.Update(迁移)方法调用中使用try-catch,但如果一次迁移失败,将不会应用其他迁移,因为它会记住异常

有没有人找到了回避这个问题的方法

这就是我写的方法:

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 + "'");
    }
}
private static void ApplyMigration()
其中T:DbContext,new()
其中TU:dbmigrations配置,new()
{
var migrationsalreadyaapplied=new List();
var dbmigator=new dbmigator(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(迁移=>
{
var migrationDate=DateTime.ParseExact(migration.Substring(0,12)、Constants.MigrationDateFormat、CultureInfo.InvariantCulture);
如果(migrationDate>dbDateCreated)
dbMigrator.Update(迁移);
其他的
migrationsalreadyaapplied.Add(迁移);
});
使用(var dbContext=new T())
{
foreach(迁移中的var迁移已应用)
dbContext.Database.ExecuteSqlCommand(“插入到uu迁移历史记录中”)
+选择“'+迁移+”,型号,产品版本
+“从_u迁移历史记录”
+“其中MigrationId=”“+migration+””);
}
}

我现在已经解决了这个问题

在dbContext初始化器的seed方法中,我调用了一个手动填充迁移历史的方法。然后可以使用ApplyMigrations方法正常调用迁移

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());
    }
公共类UserEntitiesContextInitializer:CreateDatabaseIfNotExists
{
受保护的覆盖无效种子(UserEntitiesContext上下文)
{
//使用现有迁移更新迁移历史记录,以防止EF将其识别为挂起的迁移
DatabaseAdministration.UpdateMigrationHistory();
}
}
公共静态void updateMiderationHistory()
其中T:DbContext,new()
其中TU:dbmigrations配置,new()
{
使用(var dbContext=new T())
{
var dbmigator=new dbmigator(new TU());
var creationMigrationId=dbMigrator.GetDatabaseMigrations().Single(m=>m.Contains(“InitialCreate”);
foreach(dbMigrator.GetPendingMigrations()中的var迁移)
dbContext.Database.ExecuteSqlCommand(“插入到uu迁移历史记录中”)
+选择“'+迁移+”,型号,产品版本
+“从_u迁移历史记录”
+“其中MigrationId=”“+creationMigrationId+”);
}
}
私有静态无效应用迁移()
其中T:DbContext,new()
其中TU:dbmigrations配置,new()
{
var dbmigator=new dbmigator(new TU());
if(dbMigrator.GetPendingMigrations().Any())
Update(dbMigrator.GetPendingMigrations().Last());
}

我现在已经解决了这个问题

在dbContext初始化器的seed方法中,我调用了一个手动填充迁移历史的方法。然后可以使用ApplyMigrations方法正常调用迁移

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());
    }
公共类UserEntitiesContextInitializer:CreateDatabaseIfNotExists
{
受保护的覆盖无效种子(UserEntitiesContext上下文)
{
//使用现有迁移更新迁移历史记录,以防止EF将其识别为挂起的迁移
DatabaseAdministration.UpdateMigrationHistory();
}
}
公共静态void updateMiderationHistory()
其中T:DbContext,new()
其中TU:dbmigrations配置,new()
{
使用(var dbContext=new T())
{
var dbmigator=new dbmigator(new TU());
var creationMigrationId=dbMigrator.GetDatabaseMigrations().Single(m=>m.Contains(“InitialCreate”);
foreach(dbMigrator.GetPendingMigrations()中的var迁移)
dbContext.Database.ExecuteSqlCommand(“插入到uu迁移历史记录中”)
+选择“'+迁移+”,型号,产品版本
+“从_u迁移历史记录”
+“其中MigrationId=”“+creationMigrationId+”);
}
}
私有静态无效应用迁移()
其中T:DbContext,new()
其中TU:dbmigrations配置,new()
{
var dbmigator=new dbmigator(new TU());
if(dbMigrator.GetPendingMigrations().Any())
Update(dbMigrator.GetPendingMigrations().Last());
}