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

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

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

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

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

谢谢


当前回答

你有两个选择:

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.

其他回答

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

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

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

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

步骤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正常工作以重新脚手架。

你也可以使用

Remove-Migration -Force

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

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

Update-Database –TargetMigration

例子:

Update-Database -20180906131107_xxxx_xxxx

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

你有两个选择:

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.