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

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

是否有一些查询,我可以运行,这将告诉EF类似“忘记上次迁移,就像它从来没有存在过,它是坏的”?类似于Remove-Migration。

Edit1 我找到了适合我的解决办法。将模型更改为良好状态并运行Add-Migration TheBadMigration -Force。这将重新构建最后一个未应用的迁移。

无论如何,这仍然没有完全回答最初的问题。如果我UpdateDatabase到坏的迁移,我没有找到好方法如何回滚和创建新的迁移,排除坏的一个。

谢谢


当前回答

首先,通过这个命令更新你最后的完美迁移:

Update-Database –TargetMigration

例子:

Update-Database -20180906131107_xxxx_xxxx

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

其他回答

对于那些使用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对象资源管理器中刷新数据库,我所有的数据都被保留了,我想要恢复的迁移已经消失了:)

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

系统。InvalidOperationException:迁移'…’已经被 应用于数据库。取消应用,再试一次。如果迁移 已经应用到其他数据库,是否考虑恢复其更改 使用新的迁移。

已经有人提出了改进这一措辞的建议,但我希望错误是这样的:

运行Update-Database(最后一个良好的迁移名称)将数据库模式恢复到该状态。这个命令将 取消应用指定的迁移之后发生的所有迁移 - database就。然后您可以运行remove - migration(要删除的迁移名称)

EF Core help命令输出如下:

 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

首先,通过这个命令更新你最后的完美迁移:

Update-Database –TargetMigration

例子:

Update-Database -20180906131107_xxxx_xxxx

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

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

以及(无-迁移开关):

Update-Database 20180906131107_xxxx_xxxx

另外要注意的是,您不能在不使Model Snapshot失去同步的情况下干净地删除迁移文件夹。因此,如果你以一种艰难的方式学习到这一点,并最终在你知道应该有更改的地方进行空迁移,你可以运行(上一次迁移不需要开关):

Remove-migration

它将清理混乱并将您送回需要的位置,即使最后一个迁移文件夹是手动删除的。

对于EF 6,如果你在开发中重新搭建了很多,这里有一个单行程序。只需更新vars,然后继续使用包管理器控制台中的向上箭头来冲洗和重复。

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

你问为什么有这个必要?不确定这适用于EF6的哪个版本,但如果你的新迁移目标已经被应用,那么使用'-Force'在Add-Migration中重新脚手架,实际上不会重新脚手架,而是创建一个新文件(这是一件好事,因为你不想失去你的'Down')。如果有必要,上面的代码片段首先进行“向下”,然后-Force正常工作以重新脚手架。

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

这个问题可以通过以下步骤来解决:

将数据库恢复到上一次良好的迁移。 从实体框架项目中删除糟糕的迁移。 生成一个新的迁移并将其应用到数据库。

注意:实体框架和实体框架核心使用的命令名称略有不同

步骤1:恢复到以前的迁移

如果您还没有应用迁移,可以跳过这一部分。要将数据库模式恢复到前一点,发出Update-Database命令,并带有-TargetMigration选项,以指定最后一次良好迁移。对于EFCore使用Update-Database "Name-of-Migration"

如果您的实体框架代码位于解决方案中的不同项目中,则可能需要使用“-Project”选项或在包管理器控制台中切换默认项目。

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

对于EFCore:

Update-Database <name of last good migration>

要获得最后一次良好迁移的名称,使用' get - migrations '命令检索已应用到数据库的迁移名称列表,如果使用EFCore,则使用' get - migration '不带's'。

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。

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

对于EFCore:

Update-Database "<the migration applied before it>"

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

如果您的降级可能导致数据丢失,EF将拒绝该命令。使用'-Force'选项接受数据丢失并允许命令执行。

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

如果您正在使用实体框架核心,您可以使用'remove-migration'命令,对于实体框架,手动删除EF项目'Migrations'文件夹中不需要迁移的文件。此时,您可以自由地创建一个新的迁移并将其应用到数据库。

对于EFCore:

remove-migration name_of_bad_migration

步骤3:添加新的迁移

add-migration my_new_migration

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

update-database