我使用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核心与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按预期工作的阶段,并从头开始。

确保你的项目文件中没有错误,即使在你的迁移文件中,我在我的上一个迁移文件中有一个错误,不允许我删除它。

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

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

你也可以使用

Remove-Migration -Force

这将恢复并删除最后应用的迁移

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

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

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