实体框架优先:通过更新数据库进行迁移失败,强制进行不必要的(?)add-migration


73

我使用迁移(EF 5.0)和代码优先的方式产生了有趣的效果:

我使用GUID主键创建了一些模型。(顺便说一句:对我来说,SQL Server使用NEWSEQUENTIALID(),这很重要,这似乎是当前版本中的默认值)

在某个时候,我激活了迁移。我在初始迁移中添加了一些代码,主要是.Index()根据需要。

当我删除数据库并调用更新数据库时,出现以下错误:

无法更新数据库以匹配当前模型,因为有未决的更改并且自动迁移被禁用。将挂起的模型更改写到基于代码的迁移中,或者启用自动迁移。将DbMigrationsConfiguration.AutomaticMigrationsEnabled设置为true以启用自动迁移。您可以使用Add-Migration命令将挂起的模型更改写入基于代码的迁移。

我尝试了AutomaticMigrationsEnabled = true,但没有更改或添加任何内容就可以了!

但是由于我不想要AutomaticMigrationsEnabled,我也尝试再次删除数据库,update-database然后调用,然后再删除add-migration。我最后进行了一次额外的迁移,似乎没有任何改变(请参阅下文)。我还尝试将这些行添加到初始迁移的底部-但这不会改变任何内容。

型号之一:

[Table(Speaker.TABLENAME)]
public class Speaker : BaseModel
{
    public const String TABLENAME = "Speaker";

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    [Required]
    [MaxLength(50, ErrorMessage = "Name must be 50 characters or less")]
    public string Name { get; set; }
}

初始迁移代码:

public partial class InitialCreate : DbMigration
{
    public override void Up()
    {
        // [...]
        CreateTable(
            "dbo.Speaker",
            c => new
                {
                    Id = c.Guid(nullable: false, identity: true),
                    Name = c.String(nullable: false, maxLength: 50),
                })
            .PrimaryKey(t => t.Id)
            .Index(t => t.Name, true, false);   // added manually: unique Name
        // [...]
    }
}

internal sealed class Configuration : DbMigrationsConfiguration<MyProject.Repositories.DBContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(MyProject.Repositories.DBContext context)
    {
        // ...
    }
}

以下是由add-migration创建的代码:它似乎没有做任何新的事情-也许我缺少了什么?

public partial class UnneccessaryMigration : DbMigration
{
    public override void Up()
    {
        // isn't this the exact same code from InitialMigrations?
        AlterColumn("dbo.Speaker", "Id", c => c.Guid(nullable: false, identity: true));
        // ...
    }

    public override void Down()
    {
        //...
        AlterColumn("dbo.Speaker", "Id", c => c.Guid(nullable: false));
    }
}

所以我很好奇:我做了什么来迷失迁移的方向?我该怎么做才能使其只进行一次初始迁移?

解决方案:以下解决方法为我做到了:

  1. 我删除了数据库以及此处描述的所有迁移:https ://stackoverflow.com/a/11679386/3168401
  2. 已执行的使能迁移+添加迁移初始
  3. 将我手工制作的.Index()更改合并到文件中。现在,更新数据库可以再次工作-删除数据库时也可以重复进行。

Answers:


111

我还尝试过再次删除数据库,称为update-database,然后进行add-migration。我最后进行了一次额外的迁移,似乎没有任何改变(请参阅下文)

根据上述详细信息,我认为您首先要做的是最后一件事。如果您Update database之前运行Add-migration,它将不会使用您的迁移模式更新数据库。首先,您需要添加迁移,然后运行update命令。

使用软件包管理器控制台按此顺序尝试。

PM> Enable-migrations //You don't need this as you have already done it
PM> Add-migration Give_it_a_name
PM> Update-database

2
在这一点上也许我是错的,但是我希望能够在需要时重新创建数据库。最初的迁移不完全做到这一点吗?在我偶然发现上面描述的效果之前,使用update-database创建数据库可以正常工作。而且,一旦我添加了“一堆空白”迁移步骤,它也将起作用。
它,我

如果数据库不存在,则update database命令将重新创建数据库,并使用可用的迁移对其进行更新。如果需要更新数据库,则需要add-migration先运行update database以添加这些更改。
卡夫2014年

我很想知道为什么首先要添加“无用的”迁移。
Jim Aho 2015年

我遇到了类似的问题,发出上述命令导致引发异常,我重新启动了Visual Studio,并在启动时再次运行它们,一切都很好。
利斯莫尔

9

实体框架确实存在有关身份字段的问题。

您不能在现有表上添加GUID身份

迁移:不检测对DatabaseGeneratedOption的更改

逆向工程不会将具有默认NEWSEQUENTIALID()的GUID密钥标记为存储生成的标识

这些都不能准确描述您的问题,并且额外迁移中的Down()方法很有趣,因为当初始迁移中的CREATE TABLE似乎要设置它时,它似乎正在尝试从列中删除IDENTITY!

此外,如果使用Update-Database -ScriptUpdate-Database -Verbose以查看从这些运行SQLAlterColumn方法,你会看到SQL是相同的UpDown,实际上什么也不做。IDENTITY保持不变(对于当前版本-EF 6.0.2及更低版本)-如我链接的前两个问题中所述。

我认为您应该在额外的迁移中删除冗余代码,并且现在可以进行空迁移。您可以订阅/投票解决要解决的问题。

参考文献:

更改IDENTITY选项确实会深蹲

通过自定义迁移操作打开/关闭身份


谢谢您的提示!我要赞成这些问题。到目前为止,我可以通过删除wohole迁移文件夹,数据库和重新启动来解决问题:Enable-Migrations,add-migration,然后再次添加.Index()。这似乎有效。
它,我


1

对我来说,我像下面这样解决了它:在Visual Studio 2015中:从“视图”菜单中单击“其他Windows”,然后单击“程序包管理器控制台”,然后运行以下命令:

PM> enable-migrations

已经在项目“ mvcproject”中启用了迁移。要覆盖现有的迁移配置,请使用-Force参数。

PM> enable-migrations -Force

正在检查上下文是否以现有数据库为目标...为项目mvcproject启用了代码优先迁移。

然后在迁移文件夹下添加迁移名称,它将通过运行以下命令在解决方案资源管理器中添加所需的类

PM>Add-migration AddColumnUser

最后更新数据库

PM> update-database 

对于实际上告诉我如何启动需要在其中输入这些命令的命令提示符表示敬意。
菲利普·斯特拉特福德


0

回答您的一般性问题

所以我很好奇:我做了什么来迷失迁移的方向?我该怎么做才能使其只进行一次初始迁移?

合并了多个分支后,我刚刚收到了与您相同的错误消息,并且迁移对数据库的当前状态感到困惑。最糟糕的是,这仅发生在客户端的服务器上,而不发生在我们的开发系统上。

为了弄清楚那里发生的事情,我遇到了这份精湛的Microsoft指南:

Microsoft团队环境中的代码优先迁移指南

虽然编写该指南是为了解释团队中的迁移,但它也提供了我发现的有关迁移如何在内部工作的最佳解释,这很可能会为您所看到的行为提供一个解释。对于使用EF6或以下版本的任何人来说,花一个小时阅读所有内容都是非常值得的。

对于合并迁移后该错误消息引起此问题的任何人,使用数据库的当前状态生成空白迁移的技巧对我来说都是解决问题的方法,但是请务必确保已阅读整个指南以了解该解决方案是否可行。适合您的情况。


0

我遇到了这个问题,上面的建议没有帮助。我发现,add-migration读取当前状态并创建当前模型的签名。您必须在修改之前修改模型。顺序是这样。

  1. 修改模型
  2. 运行添加迁移

我做了相反的事情,并在修改模型之前添加了迁移(它是空的,所以我添加了新列),然后运行我的代码。

希望这可以帮助。


0

如果首先根据现有数据库将上下文模型设置为代码,则必须进行集合迁移:

Add-Migration InitialCreate –IgnoreChanges
Update-database -force

然后更改您的上下文模型并设置:

Add-migration RemoveIspositive
Update-database -force

0

我了解这是一个非常老的话题。但是,想分享我在场景中遇到消息的方式,以防可能对其他人有所帮助

  1. 我在Add-Migration <Migration_name>本地计算机上创建了一个。尚未运行update-database
  2. 同时,在父分支中有一系列提交,我必须向下合并。合并也对其进行了迁移,当我解决冲突时,最终有2个迁移被添加到我的项目中,但未通过执行update-database
  3. 现在,我不在enable-migrations -force应用程序中使用。相反,我的首选方式是执行update-database -script命令来控制所需的目标迁移。
  4. 因此,当我尝试上述命令时,我得到了相关的错误。

我的解决方案是先运行update-database -Script -TargetMigration <migration_name_from_merge>,然后update-database -Script -TargetMigration <migration_name>生成两个脚本,这些脚本可以在本地数据库上手动运行。

毋庸置疑,以上经验是在我的本地计算机上产生的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.