web-dev-qa-db-ja.com

Entity Frameworkのロールバックと不適切な移行の排除

私はC#で自分のプロジェクトにEF 6.0を使っていて、手動での移行と更新を行っています。データベースには約5回の移行がありますが、最後の移行は悪いことに気付き、それは望ましくありません。以前の移行にロールバックできることはわかっていますが、新しい(固定)移行を追加してUpdate-Databaseを実行すると、悪い移行でも適用されます。

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

実行可能なクエリがいくつかあります。これは、「前回の移行をこれまで存在しなかったようなものにするのではなく、悪かった」とEFに通知するものです。削除移行のようなもの。

Edit1自分に合った解決策が見つかりました。モデルを良好な状態に変更してAdd-Migration TheBadMigration -Forceを実行します。これは最後の、適用されていない移行を再足場にします。

とにかく、これはまだ元の質問に完全に答えていません。 UpdateDatabaseを不適切な移行に更新した場合、悪い移行を除いて、新しい移行をロールバックして作成する方法がわかりませんでした。

ありがとう

143
Martin Brabec

2つの選択肢があります。

  • あなたは悪いマイグレーションからDownを取り、それを新しいマイグレーションに入れることができます(あなたはまたモデルにその後の変更を加える必要があるでしょう)。これは効果的により良いバージョンにロールアップしています。

    私はこのオプションを複数の環境に行ったことに使っています。

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

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

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

147
Luke McGregor

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

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

ステップ1:以前の移行に復元する

データベーススキーマを以前の時点に復元するには、次のコマンドを使用します。

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 –TargetMigration: "<the migration applied before it>"

指定された移行の後に適用されたすべての移行は、最初に適用された最新の移行から順に降格されます。

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

これで、EFプロジェクトの「Migrations」フォルダから不適切な移行を削除できます。この時点で、新しい移行を自由に作成してデータベースに適用できます。

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

add-migration "new migration"

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

update-database
94
David Sopko

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フォルダを調べて、行ったことに慣れておく必要があります。しかし、Nice helpコマンドがあります。

PM> get-help entityframework

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

当初、私は自分自身でRemove-Migrationを試してみましたが、エラーコマンドが紛らわしいと思いました。

System.InvalidOperationException:移行 '...'はすでにデータベースに適用されています。適用しないでやり直してください。移行が他のデータベースに適用されている場合は、新しい移行を使用してその変更を元に戻すことを検討してください。

この表現を改善するための提案はすでにありますが、エラーに次のように書いてもらいたいです。

データベーススキーマをその状態に戻すには、Update-Database(最後の正しい移行名)を実行します。このコマンドは、移行がUpdate-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
44
Richard Logwood

まず、このコマンドで最後の完璧な移行を更新します。

Update-Database –TargetMigration

例:

Update-Database -20180906131107_xxxx_xxxx

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

4

.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

最後のマイグレーションフォルダが手動で削除されたとしても、それは混乱をきれいにしてあなたがいる必要がある場所にあなたを戻します。

1
Sum None

EF 6の場合、開発中の足場を再構築するのであれば、ここでワンライナーになります。単にvarsを更新してから、パッケージマネージャコンソールの上向き矢印を使って洗い流して繰り返してください。

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

なぜこれが必要なのでしょうか。これがどのバージョンのEF6に当てはまるのかわからないが、新しいマイグレーションターゲットがすでに適用されている場合、Add-Migrationで '-Force'を使用して再スキャフォールドすると実際には再スキャフォールドされず、代わりに新しいファイルが作成されます。あなたはあなたの「ダウン」を失いたくないからです。上記のスニペットは必要ならば最初に 'Down'をしてから-Forceは正しく足場を整えます。

0
madamission

また使用することができます

Remove-Migration -Force

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

0
Daniël Tulp