Entity Frameworkはロールバックし、不適切な移行を削除します


174

手動での移行と更新を伴うC#のプロジェクトにEF 6.0を使用しています。データベースに約5つの移行がありますが、最後の移行は不適切であり、望ましくないことに気付きました。以前の移行にロールバックできることはわかっていますが、新しい(修正された)移行を追加してUpdate-Databaseを実行すると、不正な移行も適用されます。

以前の移行にロールバックして、移行が不適切なファイルを削除しようとしました。しかし、その後、新しい移行を追加しようとすると、移行ファイルが破損しているため、データベースの更新時にエラーが発生します(より具体的には、コードの最初の行でテーブルAをBに名前変更し、次の行です)。EFは名前A-多分それはいくつかのEFバグです)。

私が実行できるクエリはありますか?これは、EFに「最後の移行が存在しなかったように忘れて、それが悪かった」のようなものを伝えるでしょうか?Remove-Migrationのようなもの。

Edit1 自分に適したソリューションを見つけました。モデルを良好な状態に変更して実行しAdd-Migration TheBadMigration -Forceます。これにより、適用されていない最後のマイグレーションが再足場されます。

とにかく、これはまだ元の質問に完全には答えていません。データベースを不正な移行に更新した場合、不良な移行を除いて、新しい移行をロールバックして作成する方法が見つかりませんでした。

ありがとう


Visual Studioを再起動する必要があり、それが正常に機能し始めました。これは、実際にはデータベースを実際に更新せずに移行をいじった後、すでに数回起こっていました。そのため、ツールで何か奇妙なことが起こっています。
Andrei Dvoynos

回答:


167

次の2つのオプションがあります。

  • 悪い移行からダウンを取り、それを新しい移行に入れることができます(モデルにその後の変更を加える必要もあります)。これは事実上、より良いバージョンにロールアップされます。

    このオプションは、複数の環境に移動したものに使用します。

  • もう1つのオプションはUpdate-Database –TargetMigration: TheLastGoodMigration、デプロイされたデータベースに対して実際に実行してから、ソリューションから移行を削除することです。これはちょっとしたスマッシュの代替手段であり、不良バージョンでデプロイされたデータベースに対して実行する必要があります。

    注:移行を再足場するには、を使用できますAdd-Migration [existingname] -Force。ただし、これにより既存の移行が上書きされるため、既存の移行をデータベースから削除した場合にのみこれを実行してください。これは、既存の移行ファイルを削除して実行するのと同じことを行いますadd-migration

    開発中にこのオプションを使用します。


1
ハルクスマッシュオプションは機能しません。データベースへの不正な移行はまだ適用していません。試しましたが、元の質問で指定したテーブル名のため、うまくいきませんでした。最初のオプションはあまり好きではありません。移行のコードを変更する必要があるからです。私がそれをうまくやらなければ、私はそれをすべて壊すことができます。
Martin Brabec 2014年

8
悪い移行をまだ適用していない場合は、それを削除して、足場を再構築するか、壊れた移行を修正することを妨げるものは何もありません。
愛されない14

4
「ハルクスマッシュ」が答えです。開発時に機能し、見逃した移行に何かを追加したいのです。Martinにとってそれが機能しなかった理由は無関係である(またはおそらくデータベーススキーマを手動で変更することに関連している)
rethenhouser2

1
@BenRethmeierは原則として、開発中のみハルクスマッシュオプションを使用します。本番環境では、問題を修正するために常に新しい移行を作成します。その理由は、データベースをダウングレードする場合は手動による介入が必要になるためです。製品に手動で介入する必要があるものは好きではありません。
愛されていない

1
HULK SMASH !!!! ---うまくやろうとしたが、EFが再生されなかった-前回の既知の状態に戻した-(バックアップされた移行ファイル)削除、追加された移行-強制-以前の名前に変更してコードをコピーし、データベースを更新してから追加した同じ方法で2回目の移行-エラーなし-通常に戻る
Traci

127

質問が示すように、これはまだリリースされていない開発タイプの環境での移行に適用されます。

この問題は、次の手順で解決できます。データベースを最後の適切な移行に復元し、Entity Frameworkプロジェクトから不適切な移行を削除し、新しい移行を生成してデータベースに適用します。注:コメントから判断すると、EF Coreを使用している場合、これらの正確なコマンドは適用されない可能性があります。

手順1:以前の移行に復元する

まだ移行を適用していない場合は、この部分をスキップできます。データベーススキーマを以前のポイントに復元するには、-TargetMigrationオプションを指定してUpdate-Databaseコマンドを発行し、最後の適切な移行を指定します。エンティティフレームワークコードがソリューションの別のプロジェクトにある場合は、「-Project」オプションを使用するか、パッケージマネージャーコンソールでデフォルトのプロジェクトを切り替える必要があります。

Update-Database TargetMigration: <name of last good migration>

最後の適切な移行の名前を取得するには、「Get-Migrations」コマンドを使用して、データベースに適用されている移行名のリストを取得します。

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>"

指定されたマイグレーションの後に適用されたすべてのマイグレーションは、最初に適用された最新のマイグレーションから順にダウングレードされます。

ステップ2:プロジェクトから移行を削除する

remove-migration name_of_bad_migration

remove-migrationEntity Frameworkのバージョンでコマンドが使用できない場合は、不要な移行のファイルをEFプロジェクトの「移行」フォルダーから手動で削除します。この時点で、新しい移行を作成してデータベースに適用できます。

ステップ3:新しい移行を追加する

add-migration my_new_migration

ステップ4:移行をデータベースに適用する

update-database

6
EF Coreでは、Get-Migrationsが削除されたようです。
ケビンバートン

1
ステップ2 !-非常に便利な機能。@KevinBurtonが述べたように。そして add-migration "new migration"update-database
Alexander Frolov

2
Update-Database –migration: "<それより前に適用された移行>" @David Sopko
Fuat

ありがとう@AlexanderFrolov私はあなたのコメントを反映するようにソリューションを更新しました。
David Sopko

1
ステップ2の後、remove-migrationを使用する必要があります
Rahul

55

ASP.NET Core v1.0.0でEF Coreを使用しているユーザーの場合、同様の問題があり、次のコマンドを使用して修正しました(@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つしかなく、初期と不良の2つしかありません)、ダミープロジェクトで手順をテストすることをお勧めします。

現在、EF Core(v1.0.0)にはGet-Migrationsコマンドがないようです。そのため、migrationsフォルダーを調べて、行ったことに精通している必要があります。ただし、便利なヘルプコマンドがあります。

PM> get-help entityframework

VS2015 SQL Serverオブジェクトエクスプローラーでdastabaseを更新すると、すべてのデータが保持され、元に戻したい移行がなくなりました:)

最初に自分でRemove-Migrationを試してみたところ、エラーコマンドがわかりにくいことがわかりました。

System.InvalidOperationException:移行 '...'はすでにデータベースに適用されています。適用を解除して、もう一度お試しください。移行が他のデータベースに適用されている場合は、新しい移行を使用して変更を元に戻すことを検討してください。

この言い回しを改善するための提案はすでにありますが、私はこのエラーを次のように言ってください:

Update-Database(最後の適切な移行名)を実行して、データベーススキーマをその状態に戻します。このコマンドは、Update-Databaseに指定された移行後に発生したすべての移行を適用解除します。次に、Remove-Migration(削除する移行名)を実行できます。

EF Coreヘルプコマンドからの出力は次のとおりです。

 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

6

あなたも使うことができます

Remove-Migration -Force

これにより、最後に適用された移行が元に戻されて削除されます


4

まず、次のコマンドを使用して、最後の完全な移行を更新します。

Update-Database TargetMigration

例:

Update-Database -20180906131107_xxxx_xxxx

そして、未使用の移行を手動で削除します。


2
Update-Database -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides

Update-Database 20180906131107_xxxx_xxxx(ハイフンなし)私のために働いた。TargetMigrationスイッチとしてののバージョンは機能しませんでした。これらのコマンドは移動するターゲットのようです(つまり、すべてのバージョンでそれらを変更します)?
合計なし

3

.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

最後の移行フォルダが手動で削除された場合でも、混乱を解消し、必要な場所に戻ります。


0

EF 6の場合、開発で多くの再足場を組む場合は、ここに1つのライナーがあります。単にvarsを更新してから、パッケージマネージャーコンソールで上矢印を使用し続けて、すすぎ、繰り返します。

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

なぜこれが必要なのですか?これが適用されるEF6のバージョンはわかりませんが、新しい移行ターゲットがすでに適用されている場合、「-Force」を使用してAdd-Migrationで再足場を作成しても、実際には再足場が作成されず、代わりに新しいファイルが作成されます(これは適切です)ただし、「ダウン」を失いたくないためです。上記のスニペットは、必要に応じて最初に「ダウン」を実行してから、-Forceが適切に機能して足場を再構築します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.