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

时间:2014-03-27 07:01:14

标签: c# entity-framework migration rollback

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

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

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

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

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

由于

8 个答案:

答案 0 :(得分:144)

您有两个选择:

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

    我对已经进入多个环境的事情使用此选项。

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

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

    相同

    我在开发时使用此选项。

答案 1 :(得分:89)

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

这个问题可以在这些步骤中解决,第一步是将数据库恢复到上一次良好的迁移,然后从Entity Framework项目中删除错误的迁移,此时,您将能够生成一个新的迁移并将其应用于数据库。 注意:从评论中判断,如果您使用EF Core,这些确切的命令可能不再适用。

第1步:恢复到之前的迁移

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

Update-Database –TargetMigration: <name of last good migration>

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

使用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

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

Update-Database –TargetMigration: "<the migration applied before it>"

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

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

您现在可以从EF项目中删除错误的迁移&#39;迁移&#39;夹。此时,您可以自由创建新的迁移并将其应用于数据库。

第3步:添加新迁移

add-migration "new migration"

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

update-database

答案 2 :(得分:43)

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

Update-Database <Name of last good migration>
Remove-Migration

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

PM> Update-Database CreateInitialDatabase
Done.
PM> Remove-Migration
Done.
PM> 

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

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

PM> get-help entityframework

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

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

  

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

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

  

运行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

答案 3 :(得分:3)

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

Update-Database –TargetMigration

示例:

Update-Database -20180906131107_xxxx_xxxx

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

答案 4 :(得分:1)

从.NET Core 2.2开始,TargetMigration似乎不见了:

get-help Update-Database

NAME
    Update-Database

SYNOPSIS
    Updates the database to a specified migration.


SYNTAX
    Update-Database [[-Migration] <String>] [-Context <String>] [-Project <String>] [-StartupProject <String>] [<CommonParameters>]


DESCRIPTION
    Updates the database to a specified migration.


RELATED LINKS
    Script-Migration
    about_EntityFrameworkCore 

REMARKS
    To see the examples, type: "get-help Update-Database -examples".
    For more information, type: "get-help Update-Database -detailed".
    For technical information, type: "get-help Update-Database -full".
    For online help, type: "get-help Update-Database -online"

所以这对我现在有用:

Update-Database -Migration 20180906131107_xxxx_xxxx

以及(没有-Migration开关):

Update-Database 20180906131107_xxxx_xxxx

请注意,如果不使模型快照不同步,就无法再干净地删除迁移文件夹。因此,如果您以艰辛的方式学习了此知识,并在知道应该进行更改的空迁移中结束工作,则可以运行(上一次迁移无需任何开关):

Remove-migration

即使最后一个迁移文件夹已被手动删除,它也会清理混乱并把您带回您需要的位置。

答案 5 :(得分:1)

我将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>

我必须使用:

dotnet ef database update <Name of last good migration>

而不是

Remove-Migration

我必须使用:

dotnet ef migrations remove

对于--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.

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

答案 6 :(得分:0)

对于EF 6来说,如果你在开发过程中重新搭建了很多东西,那么这是一个单线程。只需更新vars,然后继续使用包管理器控制台中的向上箭头进行冲洗并重复。

$lastGoodTarget = "OldTargetName"; $newTarget = "NewTargetName"; Update-Database -TargetMigration "$lastGoodTarget" -Verbose; Add-Migration "$newTarget" -Verbose -Force

为什么你要问这个问题?不确定哪种版本的EF6适用,但如果您的新迁移目标已经应用,则使用&#39; -Force&#39;在Add-Migration中重新绞靠将不会实际重新构建,而是创建一个新文件(这是一件好事,因为你不想失去你的'Down&#39;)。上面的代码段是&#39; Down&#39;首先,如果有必要,然后-Force正常工作以重新支架。

答案 7 :(得分:0)

您也可以使用

Remove-Migration -Force

这将还原并删除上一次应用的迁移