C# 由于挂起的更改,更新数据库失败,但添加迁移会创建重复的迁移

C# 由于挂起的更改,更新数据库失败,但添加迁移会创建重复的迁移,c#,entity-framework,entity-framework-migrations,C#,Entity Framework,Entity Framework Migrations,我正在使用EntityFramework5.0代码优先迁移,在运行更新数据库时遇到问题。它说有待定的模型变更;但它应该是最新的,所以我跑了 Add-Migration SomeMigrationName 它会创建一个文件。。。但是,它创建了一个与先前迁移的副本基本相同的文件(如果我尝试再次更新该文件上的数据库,它将失败,并出现与尝试删除不存在的约束相关的问题)。此外,我已经能够确认“原始”迁移是基于数据库中的数据模型和_MigrationHistory表中的记录运行的 如果我删除了整个数据库,

我正在使用EntityFramework5.0代码优先迁移,在运行更新数据库时遇到问题。它说有待定的模型变更;但它应该是最新的,所以我跑了

Add-Migration SomeMigrationName
它会创建一个文件。。。但是,它创建了一个与先前迁移的副本基本相同的文件(如果我尝试再次更新该文件上的数据库,它将失败,并出现与尝试删除不存在的约束相关的问题)。此外,我已经能够确认“原始”迁移是基于数据库中的数据模型和_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);
    }
}
当我再次运行添加迁移时,该文件中的Up/Down方法与这些方法完全相同

迁移能够正确地检测到我重命名了ForeignKey列,这给我留下了深刻的印象;但这就是导致窒息的原因吗

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

更新:这不是导致此问题的最新迁移,但问题是在合并后开始的(我独自工作,但正在模拟分支上的团队工作,以了解更多有关git的信息),并试图使数据库与合并同步。这可能是由于在合并后将迁移按特定顺序放置而导致的——尽管有人指出,迁移确实按照我给它们一个空数据库时运行的顺序工作


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

我也一直看到这一点。 我不知道为什么,但愿我知道,但我的解决方案是做一个添加迁移,这将产生一个副本。 现在这个副本在编辑器中打开,然后我编辑它,这样Up和Down方法都是空的。 因此,结果是一个迁移文件什么也不做! VS很高兴,您可以无错误地更新数据库(直到下次)


我希望这能有所帮助:)

我刚刚遇到了同样的问题

一旦创建了迁移。我尝试更新数据库并收到以下消息:

无法更新数据库以匹配当前模型,因为存在 已禁用挂起的更改和自动迁移。要么写下 对基于代码的迁移的挂起模型更改或启用自动 迁移。将DbMigrationsConfiguration.AutomaticMiggrationsEnabled设置为 true以启用自动迁移。您可以使用添加迁移 命令将挂起的模型更改写入基于代码的迁移

然后,我再次生成了迁移,但它是重复的

创建迁移后,当我构建项目时,问题得到了解决。然后更新数据库脚本,找到迁移方法,就可以了。至少对我来说是这样。

。为了解决这个问题,我调用
addmigration
并将其命名为
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()
    {

    }
}

这并不是解决方案,它总是有帮助的。我也会推荐所有答案

我也有同样的问题,迈克的建议不适用于我的情况。我找到了原因

带有迁移的DLL是(sharepoint)部署的一部分,也是GAC的一部分(C:\Windows\Microsoft.NET\assembly\GAC\MSIL)

我从GAC中删除了DLL并重新启动了Visual Studio


现在“更新数据库”采用了正确的DLL,迁移工作正常。

作为对这部分问题的一般回答:

(我独自一人工作,但正在模拟分支机构的团队工作以学习 更多关于git的信息),并尝试使数据库与 合并这可能是由于将迁移放在某些应用程序中造成的吗 合并后的特定顺序

是的,很可能是这样,EF在合并后很容易感到困惑,但有可能解决它。关键是首先要理解它为什么会混淆:

从分支合并迁移时会发生什么情况?

EF产生混淆的原因是EF将数据库的当前形状存储在实际迁移文件中,它是在每次迁移下找到的resx文件中的“目标”值,例如

假设您有两个分支:

  • 分支1:将“URL”字段添加到Blog表中。目标字段现在有一个包含该额外字段的数据库描述
  • 分支2:添加新的“链接”表。同样,目标字段中的db描述现在有了那个额外的表,但它没有URL字段,因为URL字段是添加到另一个分支上的
如果现在将这两个分支合并回主分支,然后尝试运行迁移,那么很可能会遇到可怕的问题

无法更新数据库以匹配当前模型,因为存在 挂起的更改和自动迁移已禁用

该错误消息实际上是毫无帮助的误导,但错误的原因实际上很容易理解:

为什么多个分支会混淆EF?

当这两个分支合并回Master时,EF会认为它们中的任何一个现在是最后一次迁移(根据文件名开头的日期),在该迁移的目标字段中具有数据库的真实当前状态