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

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

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

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

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

谢谢


当前回答

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

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

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

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

步骤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

其他回答

对于那些使用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

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

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

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

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

步骤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

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

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

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

你有两个选择:

You can take the Down from the bad migration and put it in a new migration (you will also need to make the subsequent changes to the model). This is effectively rolling up to a better version. I use this option on things that have gone to multiple environments. The other option is to actually run Update-Database –TargetMigration: TheLastGoodMigration against your deployed database and then delete the migration from your solution. This is kinda the hulk smash alternative and requires this to be performed against any database deployed with the bad version. Note: to rescaffold the migration you can use Add-Migration [existingname] -Force. This will however overwrite your existing migration, so be sure to do this only if you have removed the existing migration from the database. This does the same thing as deleting the existing migration file and running add-migration I use this option while developing.

我使用EF核心与ASP。NET Core V2.2.6。@Richard Logwood的回答很棒,它解决了我的问题,但我需要一个不同的语法。

所以,对于那些使用EF核心与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

我不得不求助:

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.

这让我的角色回到我的DB按预期工作的阶段,并从头开始。