web-dev-qa-db-ja.com

Update-変更が保留されているためデータベースは失敗しますが、Add-Migrationは重複した移行を作成します

Entity Framework 5.0 Code First Migrationsを使用していますが、Update-Databaseの実行に問題があります。保留中のモデル変更があると書かれています。しかし、それは最新でなければならないので、私は実行します

Add-Migration SomeMigrationName

そしてそれはファイルを作成します...しかし、それは以前の移行の複製と本質的に同じファイルを作成します(私がそのファイルで再度データベースを更新しようとすると、それ以外のファイルを削除しようとすることに関連する問題で失敗します既存の制約)。さらに、DB内のデータモデルと__MigrationHistoryテーブル内のレコードの存在の両方に基づいて、「元の」移行が実行されたことを確認できました。

データベース全体を削除し、すべての移行を自動または手動で再実行すると、同じ問題が発生します。

私が持っていた「元の」移行ファイルは次のとおりです。

public partial class RenameLinkColumns : DbMigration
{
    public override void Up()
    {
        DropForeignKey("dbo.Listing", "OfferedByUserId", "dbo.User");
        DropIndex("dbo.Listing", new[] { "OfferedByUserId" });
        AddColumn("dbo.Listing", "ListedByUserId", c => c.Int(nullable: false));
        AddForeignKey("dbo.Listing", "ListedByUserId", "dbo.User", "UserId", cascadeDelete: true);
        CreateIndex("dbo.Listing", "ListedByUserId");
        DropColumn("dbo.Listing", "OfferedByUserId");
    }

    public override void Down()
    {
        AddColumn("dbo.Listing", "OfferedByUserId", c => c.Int(nullable: false));
        DropIndex("dbo.Listing", new[] { "ListedByUserId" });
        DropForeignKey("dbo.Listing", "ListedByUserId", "dbo.User");
        DropColumn("dbo.Listing", "ListedByUserId");
        CreateIndex("dbo.Listing", "OfferedByUserId");
        AddForeignKey("dbo.Listing", "OfferedByUserId", "dbo.User", "UserId", cascadeDelete: true);
    }
}

そのAdd-Migrationを再度実行したとき、そのファイルのUp/Downメソッドはこれらとまったく同じです。

移行によって、ForeignKey列の名前が変更されたことを正しく検出できたことに非常に感銘を受けました。しかし、それがこれを窒息させているのですか?

回避策があるようです。データベースとすべての移行ファイルを削除し、新しい「初期」移行を作成しましたが、可能であればこれを行わないことをお勧めします。

更新:これはnotこの問題の原因となった最新の移行でしたが、問題はマージ後に開始されました(私は一人で作業しています、しかし、gitについても学ぶためにブランチでのチームワークをシミュレートしており、マージと歩調を合わせてデータベースを取得しようとしています。これは、マージ後に特定の順序で移行を配置することから生じた可能性があります-注記されていますが、移行didは、実行されたときの順序で期待どおりに機能します私は彼らに空のDBを与えました。

さらに、この元の移行では、データを古い列から新しい列にコピーする必要があるため、テーブルにデータが含まれているときに手動で調整する必要がありました。ただし、そのファイルを手動で編集した場合としない場合でそのファイルをテストしたところ、前述の動作が発生しました。

29
Nij

この答えはそれが起こる理由を説明しています 。これを解決するには、add-migrationを呼び出してMERGEという名前を付けてから、すでに発生している重複する移行コードをすべて削除します。これは、マージされたモデルを反映するようにモデルのスナップショットを更新するためだけのものです。

例:

public partial class MERGE : DbMigration
{
    public override void Up()
    {
        // Intentionally left blank.

        // This may seem like a hack, but it is necessary when using source control.
        // When a migration is created via add-migration, EF creates 
        // an .edmx file from the current code first classes. It compares this .edmx to the .edmx stored in the last migration before this, 
        // which I'll call it's parent migration. The edmx snapshots are gzipped and stored in base64 in the resource files (.resx) if you 
        // want to see them. EF uses the difference between these two snapshots to determine what needs to be migrated.

        // When using source control it will happen that two users add entities to the model independently. The generated edmx snapshots will 
        // only have the changes that they have made. When they merge in source control, they will end up with this:

        // Migration                        |  Snapshot Contents
        // -------------------------------- | ----------------
        // 20150101_Parent Migration        |  A
        // 20150102_Developer 1's Migration |  A + Change 1
        // 20150103_Developer 2's Migration |  A + Change 2

        // So calling add-migration will create the current snapshot edmx from the Code First model and compare it to the 
        // the latest migration's snapshot, which is A + Change 2, and see that Change 1 is missing. That is why it 
        // creates a duplicate migration. We know that the migrations have already been applied, so the only thing that this 
        // migration will do is update the current snapshot .edmx so that later migrations work fine.
    }

    public override void Down()
    {

    }
}
29
Mike the Tike

これもいつも見ています。理由はわかりませんが、やりたかったのですが、私の解決策は、重複を作成する追加移行を行うことです。これで、この複製がエディターで開き、編集して、UpメソッドとDownメソッドが空になります。したがって、結果は何もしない移行ファイルになります。 VSは満足しており、データベースの更新をエラーなしで実行できます(次回まで)。

これがお役に立てば幸いです:)

4
Lars

質問のこの部分に対する一般的な答えとして:

(私は一人で作業していますが、gitについても学ぶためにブランチでのチームワークをシミュレートしています)、マージと歩調を合わせてデータベースを取得しようとしています。これは、マージ後に特定の順序で移行を配置することから生じた可能性があります

はい、そうかもしれません。マージ後にEFが混乱するのはかなり簡単ですが、それを解決することは可能です。重要なのは、そもそもなぜ混乱したのかを理解することです。

移行がブランチからマージされるとどうなりますか?

EFが混乱する理由は、EFがデータベースの現在の形状を実際の移行ファイルに保存するためです。これは、各移行で見つかったresxファイルの「ターゲット」値です。

migration file in solution Explorer showing child .resx file

migration resx file showing the Target

2つのブランチがあると想像してください。

  • ブランチ1:ブログテーブルに「URL」フィールドを追加します。ターゲットフィールドには、その追加フィールドを含むデータベースの説明が含まれるようになりました
  • ブランチ2:新しい「リンク」テーブルを追加します。繰り返しになりますが、Targetフィールドのdb記述にはその余分なテーブルがありますが、別のブランチで追加されたURLフィールドはありません。

これらのブランチの両方をマスターブランチにマージしてから移行を実行しようとすると、恐ろしいことになります。

保留中の変更があり、自動移行が無効になっているため、現在のモデルに一致するようにデータベースを更新できません...

そのエラーメッセージは本当に役に立たない誤解を招くものですが、エラーの原因は実際にはかなり簡単に理解できます。

複数のブランチがEFを混乱させるのはなぜですか?

2つのブランチがマスターにマージされたとき、どちらが最後の移行であるか(ファイル名の先頭の日付による)、EFは、その移行の[ターゲット]フィールドにデータベースの実際の現在の状態があると見なします。

ただし、上記で見たように、ブランチ1とブランチ2はどちらも、データベースの実際の状態について異なるビューを持っており(1つは新しいURLフィールドがあると考え、もう1つは新しいリンクフィールドがあると考えています)、役に立たないことになりましたbothは間違っています。これは、データベースに両方のフィールドがあるためです。

エラーメッセージは、EFが移行の実際のステップからDBの予想される状態を計算し、それをターゲットと比較して、それらが異なることを検出したために発生します。

修正方法

これらすべての解決策は、EFに、プロジェクト内の現在のすべての移行に基づいてデータベースの状態を再計算させ、allで行われた変更を含むターゲット値に更新することです。 移行。

これを行う最も簡単な方法は、次のコマンドを使用して、「空白」の移行を追加することです。

Add-Migration <pick_a_name> –IgnoreChanges

別のアプローチは、最終的な移行でターゲット値を上書きすることです。

マニュアルを参照してください..

上記のすべては、一般的な移行と、次の場所にあるチーム環境を理解するための優れたガイドの概要です。

チーム環境でのMicrosoftのコードファーストマイグレーション

そのドキュメントは、EFの日々の問題を非常に多く理解しているため、すべてのEFエラーメッセージで参照する必要があります。

1
tomRedox

これは解決策ではなく、常に役立ちます。私もすべての答えをお勧めします。

私は同じ問題を抱えていましたが、マイクからの提案は私の場合には当てはまりません。理由がわかりました...

[〜#〜] dll [〜#〜]移行ありの一部でした(共有ポイント)展開およびGAC( C:\ Windows\Microsoft.NET\Assembly\GAC_MSIL)。

DLLをGACから削除し、VisualStudioを再起動しました。

これで、「update-database」は正しいDLLを取り、移行は正常に機能しました。

0

私はちょうど同じ問題に直面しました。

移行が作成されたら。データベースを更新しようとすると、次のメッセージが表示されました。

保留中の変更があり、自動移行が無効になっているため、現在のモデルに一致するようにデータベースを更新できません。保留中のモデル変更をコードベースの移行に書き込むか、自動移行を有効にします。自動移行を有効にするには、DbMigrationsConfiguration.AutomaticMigrationsEnabledをtrueに設定します。 Add-Migrationコマンドを使用して、保留中のモデル変更をコードベースの移行に書き込むことができます。

次に、移行を再度生成しましたが、複製されました。

移行を作成した後、i プロジェクトをビルドのときに問題が解決しました。次に、Update-Databaseスクリプトが移行方法を見つけ、それが機能します。少なくとも私の場合は。

0
Vic