【问题标题】:How to recreate migrations from scratch如何从头开始重新创建迁移
【发布时间】:2013-07-17 19:29:21
【问题描述】:

我最近从 EF6 alpha 1-3 升级到 EF6 beta 1。This 意味着我必须重新创建使用 alpha 版本创建的所有迁移。

所以我尝试回滚到使用 EF5 创建的迁移。但是我遇到了错误在表上引入 FOREIGN KEY 约束可能会导致循环或多个级联路径。我认为这是因为当我为完全相同的问题修复 Up 迁移时,我忽略了修复 Down 迁移。 (之前应该看过this

无论如何,我没有尝试全部修复,而是尝试重置所有迁移 - 如 here 所述。我删除了数据库中的迁移表和所有迁移 .cs 文件,然后在包管理器 Enable-Migrations -EnableAutomaticMigrations -ForceAdd-Migration Initial

当我尝试使用现有的数据库初始化程序(自动迁移错误)运行我的应用程序时,它失败了,因为它试图创建已经存在的表。所以我将初始化程序更改为Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>())

这次我得到了在表上引入 FOREIGN KEY 约束可能会在初始化期间再次导致循环或多个级联路径问题

所以我将迁移文件中的所有cascadeDelete: true 更改为cascadeDelete: false

但我仍然遇到同样的错误!

更新 1 我删除了迁移文件中除了创建 1 个表之外的所有内容,但出现了同样的错误。某处一定有某种缓存,或者它正在拾取我不知道的文件,或者它正在后台生成自己的迁移

更新 2 我认为在使用 DropCreateDatabaseAlways 时,EF 必须始终生成迁移,而且在迁移文件中将 cascadeDelete 更改为 false 是错误的做法。它应该在 FluentAPI 中完成。所以我将这一行 modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 添加到 onmodelcreating 中。而且我还删除了初始迁移文件。然后我运行了应用程序,它正确地生成了一个数据库。我以为我已经破解了它,但是....

我更改了初始化以使用我原来的配置文件:

internal sealed class Configuration : DbMigrationsConfiguration<SID2013Context>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            AutomaticMigrationDataLossAllowed = true;
        }

         protected override void Seed(etc..
}

然后我运行应用程序,它报告模型已更改。所以我做了 Add-Migration Update-Database 并创建了一个用于创建数据库的迁移文件。

现在的问题是,当我运行应用程序时,它会尝试运行另一个更新(即使 AutomaticMigrationsEnabled = false)。我再次得到“数据库中已经有一个名为'xxx'的对象”问题。迁移表中有一个条目与配置文件的名称不匹配。

【问题讨论】:

  • 许多更改数据库以删除现有索引/es 上删除时的级联然后重试。在代码中重复。即在代码中添加一个 csacade on delete false 以确保。
  • 我已经删除了我现有的数据库。我已更改连接字符串中初始目录的名称。外键约束一定有问题。 Mybe是时候看看正在生成的sql了....

标签: entity-framework entity-framework-migrations


【解决方案1】:

如果您想使用现有数据库开始“代码优先迁移”工作,您可以执行以下操作:

  1. 我运行添加迁移“InitialMigrations”。
  2. 它探索现有数据库并将其作为迁移步骤。
  3. 暂时删除“InitialMigrations”步骤的内容:

    public partial class InitialMigrations : DbMigration {
        public override void Up()
        {
            //...
            //...
        }
    
        public override void Down()
        {
            //...
            //...
        } 
    }
    
  4. 我运行更新数据库

  5. 这会在 __MigrationHistory 表中创建相应的条目。
  6. 恢复“InitialMigration”Go 的内容以在空数据库上正常工作。

就是这样。

更新:初始化程序

据我了解,“DropCreateDatabaseAlways”总是删除和创建数据库。这只能用于第一次安装。如果您有一个正常工作的安装启动板,则会删除所有数据。这就是我危险的原因。

我基于这篇文章:coding.abel.nu/2012/03/…我自己的初始化器我正在使用。我会写。

种子肯定会被执行,所以这个方法会产生相同的结果,但即使你不运行安装,而是运行升级,它也能工作。

public partial class MyEntities : DbContext
{
   static MyEntities()
   { 
       Database.SetInitializer<MyEntities>(new ValidateDatabase<MyEntities>());
   }
}
/// <summary>
/// http://coding.abel.nu/2012/03/prevent-ef-migrations-from-creating-or-changing-the-database/
/// </summary>
/// <typeparam name="TContext"></typeparam>
public class ValidateDatabase<TContext> : IDatabaseInitializer<TContext>
  where TContext : DbContext
{
    public void InitializeDatabase(TContext context)
    {
        if (!context.Database.Exists())
        {
            throw new ConfigurationErrorsException(
              "Database does not exist");
        }
        else
        {
            if (!context.Database.CompatibleWithModel(true))
            {
                //from:
                //http://stackoverflow.com/questions/11611322/ef-4-3-code-first-migrations-seed-per-migration
                var cfg = new Migrations.Configuration();
                var migrator = new DbMigrator(cfg);

                ///Last in the db, (first, the reverse order)
                var dbLast = migrator.GetDatabaseMigrations().FirstOrDefault();
                ///last in the app
                var appLast = migrator.GetLocalMigrations().LastOrDefault();
                ///what is missing
                var pendings = string.Join(", ", migrator.GetPendingMigrations());
                throw new InvalidOperationException(
                  string.Format("The database ({0}) is not compatible with the entity model ({1}). Pending migrations: {2}",
                    dbLast, appLast, pendings));
            }
        }
    }
}

更新:设置

安装我正在使用这样的东西:

http://coding.abel.nu/2012/04/update-database-msi-custom-action/

【讨论】:

  • 我有一个使用 Add-Migration Initial 创建的初始迁移。但是当我使用 DropCreateDatabaseAlways() 运行它时,它失败了。我假设我在部署到生产环境时需要迁移,所以我现在应该修复它而不是忽略它,不是吗?
  • 据我了解,“DropCreateDatabaseAlways”总是删除和创建数据库。这只能用于第一次安装。如果您有一个正常工作的安装启动板,则会删除所有数据。这就是我危险的原因。
  • (抱歉输入)我基于这篇文章:coding.abel.nu/2012/03/…我自己正在使用的初始化程序。我会写的。
  • 当我尝试使用现有的数据库初始化程序运行我的应用程序时,它失败了,因为它试图创建已经存在的表。所以我将初始化程序更改为 Database.SetInitializer(new DropCreateDatabaseAlways())。这没关系,因为我有一个 Seed 方法来插入基本数据。但是,如果我理解为什么即使禁用了自动迁移,它仍试图重新创建表,也许我可以回到这个话题?
  • 数据库中的 __ MigrationHistory 表中缺少初始迁移步骤的行。或者错过 __MIgrationHistory 表本身。所以这些步骤的迁移要运行。
【解决方案2】:

我最终通过手动删除数据库然后使用原始 MigrateDatabaseToLatestVersion 初始化程序运行应用程序来解决此问题。我没有意识到如果数据库不存在并且不需要使用 DropCreateDatabaseAlways 初始化程序然后更改为 MigrateDatabaseToLatestVersion

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 2021-12-05
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 2019-11-09
    • 2018-03-07
    相关资源
    最近更新 更多