【问题标题】:Entity Framework code-first: migration fails with update-database, forces unneccessary(?) add-migration实体框架代码优先:迁移失败并更新数据库,强制不必要的(?)添加迁移
【发布时间】:2014-01-24 22:51:00
【问题描述】:

我使用迁移(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. 已执行 Enable-Migrations + Add-Migration Initial
  3. 将我手工制作的 .Index() 更改合并到文件中。 现在 Update-Database 再次工作 - 在删除数据库时也会重复工作。

【问题讨论】:

    标签: c# entity-framework entity-framework-migrations


    【解决方案1】:

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

    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,您将看到UpDown 中的sql 是相同的,实际上什么都不做。 IDENTITY 保持不变(对于当前版本 - EF 6.0.2 及更低版本) - 如我链接到的前 2 个问题中所述。

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

    参考资料:

    Change IDENTITY option does diddly squat

    Switch Identity On/Off With A Custom Migration Operation

    【讨论】:

    • 感谢您的这些提示!我将支持这些问题。就目前而言,我可以通过删除整体迁移文件夹、数据库和重新启动来解决我的问题:Enable-Migrations、add-migration,然后再次添加我的 .Index()。这似乎有效。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 也许我在这一点上错了,但我希望能够在需要时重新创建数据库。最初的迁移不正是这样做的吗?在我偶然发现上述效果之前,使用 update-database 创建数据库效果很好。一旦我添加了“kid of blank”迁移步骤,它也可以工作。
    • 如果数据库不存在,更新数据库命令将重新创建数据库并使用可用的迁移更新它。如果您需要更新数据库,您需要先add-migration 并运行update database 以添加这些更改。
    • 我很想知道为什么首先添加了“无用”迁移。
    • 我遇到了类似的问题,发出上面的命令导致抛出异常,我重新启动了 Visual Studio 并在它启动时再次运行它们,它们很好。
    【解决方案3】:

    试试这个:

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

    【讨论】:

      【解决方案4】:

      对我来说,我解决了如下 在 Visual Studio 2015 中: 从查看菜单中单击其他窗口,然后单击包管理器控制台 然后运行以下命令:

      PM> enable-migrations
      

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

      PM> enable-migrations -Force
      

      正在检查上下文是否针对现有数据库... 为项目 mvcproject 启用 Code First 迁移。

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

      PM>Add-migration AddColumnUser
      

      终于更新数据库了

      PM> update-database 
      

      【讨论】:

      • 赞成告诉我如何启动我需要输入这些命令的命令提示符。
      【解决方案5】:

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

        -

      【讨论】:

        【解决方案6】:

        回答你的一般问题

        所以我很好奇:我做了什么让迁移迷失方向?还有什么 我可以通过一次初始迁移来使其正常工作吗?

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

        在试图弄清楚那里发生了什么时,我偶然发现了这个极好的微软指南:

        Microsoft's guide to Code First Migrations in Team Environments

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

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

        【讨论】:

          【解决方案7】:

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

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

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

          希望这会有所帮助。

          【讨论】:

            【解决方案8】:

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

            Add-Migration InitialCreate –IgnoreChanges
            Update-database -force
            

            然后改变你的上下文模型并设置:

            Add-migration RemoveIspositive
            Update-database -force
            

            【讨论】:

              【解决方案9】:

              我知道这是一个非常古老的线程。但是,想分享我在我的场景中是如何遇到该消息的,以防它可能对其他人有所帮助

              1. 我在本地计算机上创建了一个Add-Migration &lt;Migration_name&gt;。尚未运行 update-database
              2. 同时,在父分支中有一系列提交,我必须向下合并。合并也有一个迁移到它,当我修复冲突时,我最终有 2 个迁移被添加到我的项目中,但没有通过 update-database 执行。
              3. 现在我不在我的应用程序中使用enable-migrations -force。而我更喜欢的方式是执行update-database -script 命令来控制我需要的目标迁移。
              4. 因此,当我尝试上述命令时,我收到了相关错误。

              我的解决方案是运行 update-database -Script -TargetMigration &lt;migration_name_from_merge&gt;,然后运行我的 update-database -Script -TargetMigration &lt;migration_name&gt;,它生成了 2 个脚本,我可以在本地数据库上手动运行这些脚本。

              上面的经验不用说是在我的本地机器上。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-12-29
                • 1970-01-01
                • 2013-04-02
                相关资源
                最近更新 更多