实体框架代码优先:迁移失败,更新数据库,强制不必要的(?)添加迁移

时间:2014-01-07 09:52:44

标签: entity-framework ef-migrations

我使用迁移(EF 5.0)和代码优先有一个有趣的效果:

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

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

当我删除数据库并调用update-database时,出现以下错误:

  

无法更新数据库以匹配当前模型,因为那里   正在等待更改并禁用自动迁移。要么写   挂起的模型更改为基于代码的迁移或启用   自动迁移。组   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()更改到文件中。 现在,Update-Database再次工作 - 在删除数据库时也会重复工作。

9 个答案:

答案 0 :(得分:99)

  

我还尝试再次删除数据库,称为update-database和   然后添加迁移。我最终得到了一个额外的迁移   不要改变任何东西(见下文)

基于以上细节,我认为你先做了最后一件事。如果在Update database之前运行Add-migration,则不会使用迁移模式更新数据库。首先,您需要添加迁移,然后运行更新命令。

使用包管理器控制台以此顺序尝试它们。

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

答案 1 :(得分:9)

实体框架在身份字段方面确实存在一些问题。

You can't add GUID identity on existing table

Migrations: does not detect changes to DatabaseGeneratedOption

Reverse engineering does not mark GUID keys with default NEWSEQUENTIALID() as store generated identities

这些都没有完全描述您的问题,而额外迁移中的Down()方法很有意思,因为当初始迁移中的CREATE TABLE似乎设置它时,它似乎试图从列中删除IDENTITY!

此外,如果您使用Update-Database -ScriptUpdate-Database -Verbose来查看从这些AlterColumn方法运行的sql,您会看到Up和{中的sql相同{1}},实际上什么也没做。 IDENTITY保持不变(对于当前版本 - EF 6.0.2及更低版本) - 如我链接的前两个问题所述。

我认为您应该删除额外迁移中的冗余代码,并暂时使用空迁移。您可以订阅/投票支持要解决的问题。

参考文献:

Change IDENTITY option does diddly squat

Switch Identity On/Off With A Custom Migration Operation

答案 2 :(得分:2)

试试这个:

PM> Enable-migrations -force
PM> Add-migration MigrationName
PM> Update-database -force

答案 3 :(得分:1)

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

PM> enable-migrations

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

PM> enable-migrations -Force

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

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

PM>Add-migration AddColumnUser

最后更新数据库

PM> update-database 

答案 4 :(得分:0)

使用VS2019,MVC5时-在Migrations文件夹下查找文件Configuration.cs  编辑:AutomaticMigrationsEnabled = true

     --

答案 5 :(得分:0)

回答您关于

的一般问题
  

所以我很好奇:我做了些什么来迷惑迁移?还有什么   我该怎么做才能只进行一次初始迁移?

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

在尝试弄清那里发生的事情时,我遇到了这份精湛的Microsoft指南:

Microsoft's guide to Code First Migrations in Team Environments

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

对于合并迁移后该错误消息提出此问题的任何人,generating a blank migration with the current state of the database的技巧为我解决了所有问题,但请务必阅读完整的指南以了解该解决方案是否适合您情况。

答案 6 :(得分:0)

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

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

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

希望这会有所帮助。

答案 7 :(得分:0)

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

 select ent from OpSubject_vr ent where okved_id_mult.id not in
   ( select O.id from OpSprOkved O)

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

Add-Migration InitialCreate –IgnoreChanges
Update-database -force

答案 8 :(得分: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>,它生成了2个可以在本地数据库上手动运行的脚本。

无需赘述,我的本地计算机就是上述经验。