实体框架回滚并删除错误的迁移
本文关键字:错误 迁移 删除 框架 实体 | 更新日期: 2023-09-27 17:53:46
我在c#中使用EF 6.0进行手动迁移和更新。我在数据库上有大约5次迁移,但我意识到最后一次迁移很糟糕,我不想要它。我知道我可以回滚到以前的迁移,但是当我添加一个新的(固定的)迁移并运行Update-Database时,即使是错误的迁移也会被应用。
我试图回滚到以前的迁移并删除迁移错误的文件。但是,当我尝试添加新的迁移时,我在更新数据库时得到错误,因为迁移文件已损坏(更具体地说,第一行代码将表A重命名为B,然后是下一行,EF正在尝试以名称A更新表-可能是一些EF错误)。
是否有一些查询我可以运行,这将告诉EF类似"忘记上次迁移,就像它从未存在过,它是坏的"?比如Remove-Migration.
Edit1 我找到了适合我的解决办法。将模型更改为良好状态并运行Add-Migration TheBadMigration -Force
。这将重新构建上次未应用的迁移。
无论如何,这仍然没有完全回答原来的问题。如果我updateddatabase到错误的迁移,我没有找到如何回滚和创建新迁移的好方法,排除错误的迁移。
谢谢
你有两个选择:
-
您可以从错误的迁移中取出Down,并将其放入新的迁移中(您还需要对模型进行后续更改)。这实际上是一个更好的版本。
我使用这个选项的东西已经在多个环境
-
另一种选择是对已部署的数据库实际运行
Update-Database –TargetMigration: TheLastGoodMigration
,然后从解决方案中删除迁移。这有点像hulk smash的替代方案,并且需要对任何部署了错误版本的数据库执行此操作。注:要重新进行迁移,可以使用
所做的事情相同Add-Migration [existingname] -Force
。但是,这将覆盖您现有的迁移,因此请确保仅在从数据库中删除了现有迁移后才执行此操作。这与删除现有迁移文件并运行add-migration
我在开发时使用这个选项
正如问题所指出的,这适用于尚未发布的开发类型环境中的迁移。
这个问题可以通过以下步骤解决:
- 将您的数据库恢复到上次良好迁移。
- 从实体框架项目中删除错误的迁移。
- 生成一个新的迁移并将其应用到数据库。
注意:实体框架和实体框架核心使用略有不同的命令名称
步骤1:恢复到以前的迁移
如果您还没有应用您的迁移,您可以跳过这一部分。要将数据库模式恢复到以前的点,请使用带有-TargetMigration选项的Update-Database命令来指定上一次良好的迁移。对于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将删除上次应用的迁移。如果您有一个更复杂的场景,需要删除多个迁移(我只有两个,初始的和错误的),我建议您在一个虚拟项目中测试这些步骤。
目前在EF Core (v1.0.0)中似乎没有Get-Migrations命令,因此您必须查看您的迁移文件夹并熟悉您所做的操作。但是,有一个很好的帮助命令:
PM> get-help entityframework
在VS2015 SQL Server对象资源管理器中刷新数据库,保留了我所有的数据,并且我想要恢复的迁移已经消失了:)
最初我尝试了Remove-Migration本身,发现错误命令令人困惑:
系统。InvalidOperationException: The migration '…已经是。应用于数据库。取消应用,然后再试一次。如果迁移已应用于其他数据库,是否考虑恢复其更改使用新的迁移。
已经有关于改进这种措辞的建议,但我希望错误这样说:
运行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
您也可以使用
Remove-Migration -Force
这将恢复并删除最后应用的迁移
我正在使用EF Core与ASP。. NET Core V2.2.6@Richard Logwood的回答很好,它解决了我的问题,但我需要一种不同的语法。
所以,对于那些使用EF Core与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
对于--help
,我必须使用:
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按预期工作的阶段,并从头开始。
首先,通过以下命令更新最后一次完美迁移:
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
以及(无-Migration
开关):
Update-Database 20180906131107_xxxx_xxxx
在添加的注释中,您不能再干净地删除迁移文件夹而不使您的模型快照失去同步。因此,如果您以艰难的方式了解到这一点,并且在知道应该进行更改的情况下以空迁移结束,则可以运行(上次迁移不需要开关):
Remove-migration
它将清理混乱并将您放回到您需要的地方,即使最后一个迁移文件夹是手动删除的。
对于EF 6,如果您在开发中重新构建了很多,这里有一个一行代码。只需更新变量,然后继续使用包管理器控制台中的向上箭头来冲洗和重复。
$lastGoodTarget = "OldTargetName"; $newTarget = "NewTargetName"; Update-Database -TargetMigration "$lastGoodTarget" -Verbose; Add-Migration "$newTarget" -Verbose -Force
你问为什么这是必要的?不确定EF6的哪个版本适用,但如果你的新迁移目标已经被应用,那么使用"-Force"在Add-Migration中重新脚手架实际上不会重新脚手架,而是创建一个新文件(这是一件好事,虽然因为你不想失去你的"Down")。上面的代码片段在必要时先执行"Down",然后再执行"force"来正确地重新脚手架。
确保您在项目文件中没有错误,甚至在您的迁移文件中,我在上次迁移文件中有一个错误,并且不允许我删除