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


174

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

我试图回滚到以前的迁移并删除迁移错误的文件。但是,当我尝试添加新的迁移时,更新数据库时会出错,因为迁移文件已损坏(更具体地说,第一行代码将表A重命名为B,然后是下一行,EF尝试使用名称A-可能是一些EF错误)。

我是否可以运行一些查询,该查询将告诉EF诸如“忘记上一次没有出现的上次迁移,那是很糟糕的事情”?类似于Remove-Migration。

Edit1 我发现适合我的解决方案。将模型更改为良好状态并运行Add-Migration TheBadMigration -Force。这将重新构建上一个未应用的迁移。

无论如何,这仍然不能完全回答原始问题。如果我将UpdateDatabase迁移至错误的迁移,则我没有找到好的方法来回滚并创建新的迁移,排除了错误的迁移。

谢谢


我必须重新启动Visual Studio,然后它才能正常工作。对于我来说,这已经发生过两次了,总是在搞乱迁移而没有实际更新数据库之后发生的,所以那里的工具发生了一些奇怪的事情。
Andrei Dvoynos

Answers:


167

您有2个选择:

  • 您可以从不良迁移中删除Down并将其放入新迁移中(您还需要对模型进行后续更改)。这实际上可以汇总到更好的版本。

    我将这个选项用于已进入多个环境的事物。

  • 另一个选择是Update-Database –TargetMigration: TheLastGoodMigration针对已部署的数据库实际运行,然后从解决方案中删除迁移。这有点麻烦,需要对部署有该错误版本的任何数据库执行此操作。

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

    我在开发时使用此选项。


1
绿巨人粉碎选项不起作用。我尚未将错误迁移应用于数据库。我尝试了一下,但是没有用,因为我在原始问题中指定了表名。我不喜欢的第一个选项是,因为看起来我必须更改迁移代码。如果做得不好,我可以将其分解。
Martin Brabec 2014年

8
如果尚未应用错误的迁移,则没有什么可以阻止您删除它并重新折叠或纠正中断的迁移。
不被爱

4
答案是“麻烦”,它在开发时对我有用,并且我想为我错过的迁移添加一些东西。我认为它对Martin无效的原因无关(或可能与手动更改数据库模式有关)
rethenhouser2

1
@BenRethmeier作为一般规则,我仅在开发时才使用hulk smash选项。在生产中,我总是创建一个新的迁移来纠正此问题。原因是如果要降级数据库,则需要手动干预。我不喜欢任何需要人工干预的产品。
2015年

1
笨拙!!!! ---我试着保持友善,但EF却没有播放-我恢复为上一个已知-(备份了迁移文件)删除,添加了迁移-强制-重命名为以前的代码并复制了代码。然后添加了更新数据库第二次迁移的方式相同-没有错误-恢复正常
Traci 2015年

127

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

可通过以下步骤解决此问题:将数据库还原到上一次良好的迁移,从Entity Framework项目中删除不良的迁移,生成新的迁移并将其应用于数据库。注意:如果使用的是EF Core,从注释中判断,这些确切的命令可能不再适用。

步骤1:还原至先前的迁移

如果您尚未应用迁移,则可以跳过此部分。要将数据库架构还原到先前的位置,请发出带有-TargetMigration选项的Update-Database命令,指定最后一次良好的迁移。如果您的实体框架代码位于解决方案中的其他项目中,则可能需要使用“ -Project”选项或在程序包管理器控制台中切换默认项目。

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:从专案中删除迁移

remove-migration name_of_bad_migration

如果该remove-migration命令在您的Entity Framework版本中不可用,请手动删除EF项目“迁移”文件夹中不需要的迁移文件。此时,您可以自由创建一个新的迁移并将其应用于数据库。

步骤3:添加新迁移

add-migration my_new_migration

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

update-database

6
使用EF Core,似乎已删除Get-Migrations。
凯文·伯顿

1
第2步 !-非常有用的功能。正如@KevinBurton所提到的。然后 add-migration "new migration"update-database
亚历山大·弗洛洛夫

2
更新数据库–migration:“ <在其之前应用了迁移>” @David Sopko
Fuat

感谢@AlexanderFrolov我更新了解决方案以反映您的评论。
大卫·索普科

1
我们需要在步骤2之后使用remove-migration
Rahul

55

对于将EF Core与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命令,因此您必须查看自己的Migrations文件夹并熟悉所做的工作。但是,有一个很好的帮助命令:

PM> get-help entityframework

在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


4

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

Update-Database TargetMigration

例:

Update-Database -20180906131107_xxxx_xxxx

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


2
它应该是:Update-Database -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides

Update-Database 20180906131107_xxxx_xxxx(没有连字符)为我工作。没有任何版本的TargetMigration开关有效。这些命令似乎是一个移动的目标(即在每个版本中都对其进行更改)?
总和没有

3

从.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

即使最后一个迁移文件夹已被手动删除,它也将清理混乱并把您带回原处。


0

对于EF 6,如果您要重新开发很多脚手架,那么这里是一线。只需更新变量,然后继续使用程序包管理器控制台中的向上箭头进行冲洗和重复即可。

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

您为什么要这样做?不知道这适用于EF6的哪个版本,但是如果已经应用了新的迁移目标,则在添加迁移中使用“ -Force”重新进行脚手架实际上不会重新进行脚手架,而是创建一个新文件(这很好事情,因为您不想失去'Down')。上面的代码段在必要时先执行“向下”操作,然后-Force可以正常工作以重新构建脚手架。

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.