web-dev-qa-db-ja.com

MVCで最初にEntityFrameworkコードを使用して既存のデータベースを更新する

私のMVCアプリケーションでは、Entity Framework 6を​​使用し、コードファーストアプローチでデータベースを作成しました。しばらくして、新しい列を追加し、いくつかの列を削除して、エンティティクラスの1つを更新しました。私は以下の手順に従ったデータベースにこれらの変更を反映するための:

  1. プロジェクト内のフォルダの移行を削除しました。
  2. データベースの__MigrationHistoryテーブルを削除しました。
  3. そして、パッケージマネージャコンソールで次のコマンドを実行します。
    Enable-Migrations -EnableAutomaticMigrations -Force

  4. 構成ファイルに次の行を追加します。
    AutomaticMigrationsEnabled = true;
    AutomaticMigrationDataLossAllowed = true;

  5. 実行:
    Add-Migration Initial

  6. そして最後に、実行します。
    pdate-Database -Verbose

ただし、エラーが発生します「データベースにはすでに「xxx」という名前のオブジェクトがあります。」

この問題を取り除くために、5番目のステップの後に作成された初期ファイルのUpメソッドのコードにコメントを付けます。これによりエラーは防止されますが、データベースでは何も変更されません(更新されたエンティティテーブルは以前と同じままです)。間違いはどこですか?あなたの助けを事前に感謝します。

これが、migration.csファイルでコメントしたUpメソッドです:

    public override void Up()
    {
        CreateTable(
            "dbo.City",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    RegionID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Region", t => t.RegionID)
            .Index(t => t.RegionID);

        CreateTable(
            "dbo.Multiplier",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Status = c.Int(nullable: false),
                    Term = c.Int(nullable: false),
                    CityID = c.Int(nullable: false),
                    WhoIsOnline = c.String(nullable: false),
                    UserId = c.String(nullable: false),
                    InstituteName = c.String(nullable: false),
                    InstituteStatusID = c.Int(nullable: false),
                    InstituteAccreditationDate = c.DateTime(nullable: false),
                    Address = c.String(nullable: false),
                    Phone = c.String(nullable: false),
                    Fax = c.String(),
                    Email = c.String(nullable: false),
                    EurodeskEmail = c.String(nullable: false),
                    WebSite = c.String(),
                    ContactName = c.String(nullable: false),
                    ContactSurname = c.String(nullable: false),
                    ContactJobTitle = c.String(),
                    ContactAssignmentDate = c.DateTime(),
                    ContactWorkingStart = c.String(),
                    ContactWorkingkEnd = c.String(),
                    ContactPhone = c.String(),
                    ContactMobile = c.String(nullable: false),
                    ContactEmail = c.String(nullable: false),
                    ContactCityID = c.Int(nullable: false),
                    LegalRepresentativeName = c.String(nullable: false),
                    LegalRepresentativeSurname = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.City", t => t.CityID)
            .ForeignKey("dbo.InstituteStatus", t => t.InstituteStatusID)
            .Index(t => t.CityID)
            .Index(t => t.InstituteStatusID);

        CreateTable(
            "dbo.InstituteStatus",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID);

        CreateTable(
            "dbo.TrainingParticipant",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    TrainingID = c.Int(nullable: false),
                    ParticipantID = c.Int(nullable: false),
                    Multiplier_ID = c.Int(),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Participant", t => t.ParticipantID)
            .ForeignKey("dbo.Training", t => t.TrainingID)
            .ForeignKey("dbo.Multiplier", t => t.Multiplier_ID)
            .Index(t => t.TrainingID)
            .Index(t => t.ParticipantID)
            .Index(t => t.Multiplier_ID);

        CreateTable(
            "dbo.Participant",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    Surname = c.String(nullable: false),
                    MultiplierID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Multiplier", t => t.MultiplierID)
            .Index(t => t.MultiplierID);

        CreateTable(
            "dbo.Training",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    Date = c.DateTime(nullable: false),
                    CityID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.City", t => t.CityID)
            .Index(t => t.CityID);

        CreateTable(
            "dbo.Region",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID);

    }


そしてこれはmigration.csファイルのDownメソッドです:

    public override void Down()
    {
        DropForeignKey("dbo.City", "RegionID", "dbo.Region");
        DropForeignKey("dbo.TrainingParticipant", "Multiplier_ID", "dbo.Multiplier");
        DropForeignKey("dbo.TrainingParticipant", "TrainingID", "dbo.Training");
        DropForeignKey("dbo.Training", "CityID", "dbo.City");
        DropForeignKey("dbo.TrainingParticipant", "ParticipantID", "dbo.Participant");
        DropForeignKey("dbo.Participant", "MultiplierID", "dbo.Multiplier");
        DropForeignKey("dbo.Multiplier", "InstituteStatusID", "dbo.InstituteStatus");
        DropForeignKey("dbo.Multiplier", "CityID", "dbo.City");
        DropIndex("dbo.Training", new[] { "CityID" });
        DropIndex("dbo.Participant", new[] { "MultiplierID" });
        DropIndex("dbo.TrainingParticipant", new[] { "Multiplier_ID" });
        DropIndex("dbo.TrainingParticipant", new[] { "ParticipantID" });
        DropIndex("dbo.TrainingParticipant", new[] { "TrainingID" });
        DropIndex("dbo.Multiplier", new[] { "InstituteStatusID" });
        DropIndex("dbo.Multiplier", new[] { "CityID" });
        DropIndex("dbo.City", new[] { "RegionID" });
        DropTable("dbo.Region");
        DropTable("dbo.Training");
        DropTable("dbo.Participant");
        DropTable("dbo.TrainingParticipant");
        DropTable("dbo.InstituteStatus");
        DropTable("dbo.Multiplier");
        DropTable("dbo.City");
    }
10
Jack

なぜステップ1〜4を実行したのですか?それはあなたが間違っていたところです。以前に生成されたデータベースがあり、スキーマに変更を加えるだけの場合は、移行を生成して適用するだけです。手順1〜4を実行することで、このデータベースに関するEntity Frameworkの知識を効果的に元に戻し、基本的に既存のデータベースでコードファーストになります。その時点で、スキーマを手動で変更するか、EntityFrameworkにスキーマを吹き飛ばして最初からやり直す必要があります。

移行を再度適用できる状態に戻る限り、移行を生成し、Upメソッドを空にするだけで正しい方向に進んでいました。ただし、これは、アプリケーションの以前の状態、つまり現在のデータベースと一致する状態に対して行う必要があります。それ以外の場合、Entity Frameworkは、コードの変更を含む作成テーブルを生成します。したがって、従う手順は次のとおりです。

  1. POCOの変更を開始する前のポイントにコードを戻します。
  2. 移行を生成します。
  3. Upメソッドのすべてを削除します
  4. update-databaseを使用して移行を適用します
  5. POCOに加えた変更を再適用します。
  6. 別の移行を生成します(これは、テーブルの作成ではなく、列の追加/変更ステートメントがあるはずです)
  7. 移行を適用します。

その後、また行ってもいいはずです。次に、コードを変更するときは、手順5と6に従ってください。

12
Chris Pratt

私はこの正確な問題を抱えています。この状況を支援するコマンド、つまり-IgnoreChangesフラグと-Forceフラグが用意されていることは注目に値します。

マルチdbContextからシングルdbContextアプリにトリミングしていました。ご想像のとおり、テーブルはすでに存在していましたが、単一のコンテキストでは、2番目のコンテキストで維持されていたテーブルはまったく新しいものではありません。

それは実際には非常に単純です(役に立たないという答えを2日間検索した結果、 EF Code First Migrationsとパッケージマネージャーのコマンドライン ...)を読むことになりました。それを処理しました。

SQLで移行フォルダと_Migrationsテーブルを削除できます…これにより、次を使用する必要があります:Enable-Migrations -Force

しかし、抜本的な対策を講じることなく、ここからピックアップできるはずです。

  1. Add-migration“ Reset” –IgnoreChanges –Force(モデル/クラスに存在する可能性のある変更を強制的に無視します–既存のデータベースの使用を開始するのに適しています)
  2. 更新-データベース(ベースとして移行ラインを書き込むだけ)
  3. Add-migration“ AddMyMigrationsToThisDb” –Force(変更を取得するためにコード内のオブジェクトモデルを強制的に反復します)
  4. データベースを更新する

これで、追加のフラグなしでAdd-MigrationとUpdate-Databaseを使用するだけで軌道に戻るはずです。

5
John Salewski