实体框架回滚并删除错误的迁移

本文关键字:错误 迁移 删除 框架 实体 | 更新日期: 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. 将您的数据库恢复到上次良好迁移。
  2. 从实体框架项目中删除错误的迁移。
  3. 生成一个新的迁移并将其应用到数据库。

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

步骤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"来正确地重新脚手架。

确保您在项目文件中没有错误,甚至在您的迁移文件中,我在上次迁移文件中有一个错误,并且不允许我删除