由于Pending Changes,Update-Database失败,但Add-Migration创建了重复迁移

Nij*_*Nij 28 c# entity-framework ef-migrations

我正在使用Entity Framework 5.0 Code First Migrations,并且遇到运行Update-Database的问题.它说有待更改的模型; 但它应该是最新的,所以我跑了

Add-Migration SomeMigrationName
Run Code Online (Sandbox Code Playgroud)

并且它创建了一个文件...但是,它创建的文件与先前的迁移基本相同(如果我再次尝试在该文件上更新数据库,则会因尝试删除非文件而失败)存在的约束).此外,我已经能够确认已经根据数据库中的数据模型以及__MigrationHistory表中的记录的存在运行了"原始"迁移!

如果我删除整个数据库,并自动或手动再次运行所有迁移,我遇到同样的问题.

我拥有的"原始"迁移文件如下:

public partial class RenameLinkColumns : DbMigration
{
    public override void Up()
    {
        DropForeignKey("dbo.Listing", "OfferedByUserId", "dbo.User");
        DropIndex("dbo.Listing", new[] { "OfferedByUserId" });
        AddColumn("dbo.Listing", "ListedByUserId", c => c.Int(nullable: false));
        AddForeignKey("dbo.Listing", "ListedByUserId", "dbo.User", "UserId", cascadeDelete: true);
        CreateIndex("dbo.Listing", "ListedByUserId");
        DropColumn("dbo.Listing", "OfferedByUserId");
    }

    public override void Down()
    {
        AddColumn("dbo.Listing", "OfferedByUserId", c => c.Int(nullable: false));
        DropIndex("dbo.Listing", new[] { "ListedByUserId" });
        DropForeignKey("dbo.Listing", "ListedByUserId", "dbo.User");
        DropColumn("dbo.Listing", "ListedByUserId");
        CreateIndex("dbo.Listing", "OfferedByUserId");
        AddForeignKey("dbo.Listing", "OfferedByUserId", "dbo.User", "UserId", cascadeDelete: true);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我再次运行Add-Migration时,该文件中的Up/Down方法与这些方法完全相同.

令我印象深刻的是,迁移能够正确地检测到我已经重命名了一个ForeignKey列; 是什么导致这种窒息?

似乎有一个解决办法:我删除了数据库和所有迁移文件,并创建了一个新的"初始"迁移,但如果可能的话,我宁愿不这样做.

更新:不是导致此问题的最新迁移,但问题在合并后开始(我正在单独工作,但我正在模拟分支上的团队工作以了解更多关于git的信息),并试图让数据库与合并.这可能是因为合并后以某种特定顺序放置迁移 - 尽管有一点需要注意,迁移确实按照我们给他们一个空数据库时的运行顺序工作.

此外,当表中包含数据时,需要手动调整此原始迁移,因为需要将数据从旧列复制到新列.但是,我在该文件中使用和不使用我的手动编辑测试了该文件,但仍然遇到了注意到的行为.

Mik*_*ike 31

这个答案解释了为什么会发生.要解决它,我调用add-migration并命名它MERGE,然后删除已经发生的任何重复的迁移代码.这只是为了更新模型快照以反映合并的模型.

例:

public partial class MERGE : DbMigration
{
    public override void Up()
    {
        // Intentionally left blank.

        // This may seem like a hack, but it is necessary when using source control.
        // When a migration is created via add-migration, EF creates 
        // an .edmx file from the current code first classes. It compares this .edmx to the .edmx stored in the last migration before this, 
        // which I'll call it's parent migration. The edmx snapshots are gzipped and stored in base64 in the resource files (.resx) if you 
        // want to see them. EF uses the difference between these two snapshots to determine what needs to be migrated.

        // When using source control it will happen that two users add entities to the model independently. The generated edmx snapshots will 
        // only have the changes that they have made. When they merge in source control, they will end up with this:

        // Migration                        |  Snapshot Contents
        // -------------------------------- | ----------------
        // 20150101_Parent Migration        |  A
        // 20150102_Developer 1's Migration |  A + Change 1
        // 20150103_Developer 2's Migration |  A + Change 2

        // So calling add-migration will create the current snapshot edmx from the Code First model and compare it to the 
        // the latest migration's snapshot, which is A + Change 2, and see that Change 1 is missing. That is why it 
        // creates a duplicate migration. We know that the migrations have already been applied, so the only thing that this 
        // migration will do is update the current snapshot .edmx so that later migrations work fine.
    }

    public override void Down()
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

```

  • 谢谢你解释这个.我已经做过这样做作为一个"修复",但不明白检查它而不理解为什么它有效. (2认同)
  • 这个工作,但它是太可怕了,我不要每次我有一个silli变化时有什么一个什么都不做迁移 (2认同)