实体框架回滚并删除错误的迁移

Mar*_*bec 160 c# migration entity-framework rollback

我在C#中使用EF 6.0进行手动迁移和更新.我在数据库上有大约5次迁移,但我意识到上次迁移很糟糕,我不想要它.我知道我可以回滚到先前的迁移,但是当我添加新的(固定的)迁移并运行Update-Database时,即使应用了错误的迁移.

我试图回滚到上一次迁移并删除迁移错误的文件.但是,当我尝试添加新的迁移时,我在更新数据库时遇到错误,因为迁移文件已损坏(更具体地说,第一行代码将表A重命名为B并且是下一行,EF正在尝试更新表名字A - 也许是一些EF错误).

是否有一些我可以运行的查询,这会告诉EF类似于"忘记上次迁移,就像它从未存在过,这很糟糕"?像删除迁移这样的东西.

Edit1 我找到了适合我的解决方案.将模型更改为良好状态并运行Add-Migration TheBadMigration -Force.这将重新构建最后的,而不是应用的迁移.

无论如何,这仍然没有完全回答原来的问题.如果我将UpdateDatabase更改为错误的迁移,我没有找到如何回滚和创建新迁移的好方法,不包括坏迁移.

谢谢

Not*_*ple 158

你有2个选择:

  • 您可以从错误的迁移中获取Down并将其置于新的迁移中(您还需要对模型进行后续更改).这实际上是一个更好的版本.

    我在已经进入多个环境的事情上使用此选项.

  • 另一种选择是实际Update-Database –TargetMigration: TheLastGoodMigration针对已部署的数据库运行,然后从解决方案中删除迁移.这有点像hulk smash替代方案,并且要求对使用坏版本部署的任何数据库执行此操作.

    注意:要重新支持您可以使用的迁移Add-Migration [existingname] -Force.但是,这将覆盖您现有的迁移,因此请确保仅在从数据库中删除现有迁移时才执行此操作.这与删除现有迁移文件并运行相同add-migration

    我在开发时使用此选项.

  • 如果您还没有应用错误的迁移,那么没有什么能阻止您删除它并重新重新加载或纠正损坏的迁移. (8认同)
  • "绿巨人粉碎"就是答案,它在开发时对我有用,我想在我错过的迁移中添加一些内容.我认为它对Martin不起作用的原因是无关的(或者可能与手动更改数据库模式有关) (4认同)
  • 绿巨人粉碎选项不起作用。我还没有将错误迁移应用到数据库。我试过了,但它不起作用,因为我在原始问题中指定了表名。第一个选项我不太喜欢,因为看起来我必须更改迁移代码。如果我做得不好,我可以把它全部毁掉。 (2认同)
  • @BenRethmeier 作为一般规则,我仅在开发时使用绿巨人粉碎选项。在产品中,我总是创建一个新的迁移来纠正问题。原因是如果您要降级数据库,则需要手动干预。我不喜欢任何需要手动干预产品的东西。 (2认同)

Dav*_*pko 110

正如问题所示,这适用于尚未发布的开发类型环境中的迁移.

这个问题可以在这些步骤来解决,第一步是将数据库恢复到最后一个良好的迁移和再下一删除你的实体框架项目的不良迁移,在这一点上,你就能产生一个新的迁移和应用它到数据库.注意:从注释中判断,如果您使用的是EF Core,则这些命令可能不再适用.

第1步:还原到以前的迁移

要将数据库架构还原到上一个点,请使用:

Update-Database –TargetMigration: <name of last good migration>
Run Code Online (Sandbox Code Playgroud)

指定上次良好的迁移.如果您尚未应用迁移,则可以跳过此部分.

使用Get-Migrations命令获取已应用于数据库的迁移名称列表.

PM> Get-Migrations
Retrieving migrations that have been applied to the target database.
201508242303096_Bad_Migration
201508211842590_The_Migration_applied_before_it
201508211440252_And_another
Run Code Online (Sandbox Code Playgroud)

此列表首先显示最近应用的迁移.在要降级的列表之后选择列表中发生的迁移,即在要降级的列表之前应用的迁移.

Update-Database –TargetMigration: "<the migration applied before it>"
Run Code Online (Sandbox Code Playgroud)

在指定的迁移之后应用的所有迁移将按照从先应用的最新迁移开始的顺序进行降级.

第2步:从项目中删除迁移

您现在可以从EF项目"迁移"文件夹中删除错误的迁移.此时,您可以自由创建新迁移并将其应用于数据库.

第3步:添加新迁移

add-migration "new migration"
Run Code Online (Sandbox Code Playgroud)

第4步:将迁移应用于数据库

update-database
Run Code Online (Sandbox Code Playgroud)

  • 使用EF Core,似乎已删除Get-Migrations. (3认同)
  • Update-Database –migration:“&lt;在它之前应用的迁移&gt;”@David Sopko (2认同)
  • 使用“dotnet tool install --global dotnet-ef”安装“dotnet ef”(EF Core 3.x)后,我能够使用“dotnet-ef migrations list --project your-project-name”列出迁移。 (2认同)

Ric*_*ood 46

对于那些使用EF Core和ASP.NET Core v1.0.0的人,我遇到了类似的问题并使用以下命令来纠正它(@ DavidSopko的帖子指出了我正确的方向,但EF Core的细节略有不同):

Update-Database <Name of last good migration>
Remove-Migration
Run Code Online (Sandbox Code Playgroud)

例如,在我当前的开发中,命令变为

PM> Update-Database CreateInitialDatabase
Done.
PM> Remove-Migration
Done.
PM> 
Run Code Online (Sandbox Code Playgroud)

Remove-Migration将删除您应用的上次迁移.如果你有一个更复杂的场景需要删除多个迁移(我只有2个,最初的和坏的),我建议你测试虚拟项目中的步骤.

目前,EF Core(v1.0.0)中似乎没有Get-Migrations命令,因此您必须查看迁移文件夹并熟悉已完成的操作.但是,有一个很好的帮助命令:

PM> get-help entityframework
Run Code Online (Sandbox Code Playgroud)

在VS2015 SQL Server对象资源管理器中刷新dastabase,我的所有数据都被保留了,我想要还原的迁移已经消失了:)

最初我尝试了Remove-Migration本身,发现错误命令令人困惑:

System.InvalidOperationException:迁移"..."已应用于数据库.取消应用并再试一次.如果迁移已应用于其他数据库,请考虑使用新迁移还原其更改.

已经有关于改进这个措辞的建议,但是我想错误地说出这样的话:

运行Update-Database(上一个良好的迁移名称)以将数据库模式恢复为该状态.此命令将取消应用指定到Update-Database的迁移后发生的所有迁移.然后,您可以运行Remove-Migration(要删除的迁移名称)

EF Core帮助命令的输出如下:

 PM> get-help entityframework
                     _/\__
               ---==/    \\
         ___  ___   |.    \|\
        | __|| __|  |  )   \\\
        | _| | _|   \_/ |  //|\\
        |___||_|       /   \\\/\\

TOPIC
    about_EntityFrameworkCore

SHORT DESCRIPTION
    Provides information about Entity Framework Core commands.

LONG DESCRIPTION
    This topic describes the Entity Framework Core commands. See https://docs.efproject.net for information on Entity Framework Core.

    The following Entity Framework cmdlets are included.

        Cmdlet                      Description
        --------------------------  ---------------------------------------------------
        Add-Migration               Adds a new migration.

        Remove-Migration            Removes the last migration.

        Scaffold-DbContext          Scaffolds a DbContext and entity type classes for a specified database.

        Script-Migration            Generates a SQL script from migrations.

        Update-Database             Updates the database to a specified migration.

        Use-DbContext               Sets the default DbContext to use.

SEE ALSO
    Add-Migration
    Remove-Migration
    Scaffold-DbContext
    Script-Migration
    Update-Database
    Use-DbContext
Run Code Online (Sandbox Code Playgroud)


Dan*_*ulp 11

你也可以使用

Remove-Migration -Force
Run Code Online (Sandbox Code Playgroud)

这将恢复并删除上次应用的迁移


小智 10

我将 EF Core 与 ASP.NET Core V2.2.6 结合使用。@Richard Logwood 的答案很棒,它解决了我的问题,但我需要不同的语法。

因此,对于那些使用 EF Core 和 ASP.NET Core V2.2.6 + 的人...

代替

Update-Database <Name of last good migration>
Run Code Online (Sandbox Code Playgroud)

我不得不使用:

dotnet ef database update <Name of last good migration>
Run Code Online (Sandbox Code Playgroud)

而不是

Remove-Migration
Run Code Online (Sandbox Code Playgroud)

我不得不使用:

dotnet ef migrations remove
Run Code Online (Sandbox Code Playgroud)

因为--help我必须使用:

dotnet ef migrations --help


Usage: dotnet ef migrations [options] [command]

Options:
  -h|--help        Show help information
  -v|--verbose     Show verbose output.
  --no-color       Don't colorize output.
  --prefix-output  Prefix output with level.

Commands:
  add     Adds a new migration.
  list    Lists available migrations.
  remove  Removes the last migration.
  script  Generates a SQL script from migrations.

Use "migrations [command] --help" for more information about a command.
Run Code Online (Sandbox Code Playgroud)

这让我回到了数据库按预期工作的阶段,并从头开始。


Abd*_*zad 6

首先,通过以下命令更新您上次的完美迁移:

\n\n
Update-Database \xe2\x80\x93TargetMigration\n
Run Code Online (Sandbox Code Playgroud)\n\n

例子:

\n\n
Update-Database -20180906131107_xxxx_xxxx\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,手动删除未使用的迁移。

\n

  • 它应该是:更新数据库-TargetMigration 20180906131107_xxxx_xxxx (3认同)