移行履歴テーブルをカスタマイズする

Note

EF6 以降のみ - このページで説明する機能、API などは、Entity Framework 6 で導入されました。 以前のバージョンを使用している場合、一部またはすべての情報は適用されません。

Note

この記事は、読者が基本的なシナリオでの Code First Migrations の使用方法を理解していると想定しています。 それ以外の方は、先に「Code First Migrations」をお読みください。

移行履歴テーブルとは

移行履歴テーブルとは、データベースに適用された移行についての詳細を Code First Migrations が格納する際に使用するテーブルです。 このデータベース テーブルは、既定で __MigrationHistory という名前が付いており、データベースに対する移行の初回適用時に作成されます。 Entity Framework 5 では、アプリケーションで Microsoft SQL Server データベースが使用されている場合、このテーブルがシステム テーブルとなっていました。 しかし、Entity Framework 6 ではこの点が変更され、移行履歴テーブルはシステム テーブルではなくなりました。

移行履歴テーブルをカスタマイズする理由

移行履歴テーブルは、Code First Migrations によってのみ使用されることが想定されており、手動で変更すると移行に支障をきたす可能性があります。 ただし、既定の構成が適さず、テーブルのカスタマイズが必要になることもあります。たとえば次のようなケースです。

  • サード パーティの移行プロバイダーを使用可能にするために列の名前やファセットを変更する必要がある
  • テーブルの名前を変更する必要がある
  • __MigrationHistory テーブルに既定以外のスキーマを使用する必要がある
  • 特定のバージョンのコンテキストに関して付加的なデータを格納する必要が生じ、そのための列を新たにテーブルに追加しなければならなくなった

ご注意ください

移行履歴テーブルの変更は強力な手段ではありますが、過度な変更を行わないよう注意が必要です。 現在、EF ランタイムでは、カスタマイズされた移行履歴テーブルにランタイムとの互換性があるかどうかのチェックは行われません。 互換性がない場合、実行時にアプリケーションが動かなくなったり予期しない振る舞いをしたりすることがあります。 データベースごとに複数のコンテキストを使用している場合、この点の重要性がさらに増します。そのようなケースでは、複数のコンテキストが同じ移行履歴テーブルを使用して移行についての情報を格納する可能性があります。

移行履歴テーブルをカスタマイズする方法

始める前に、移行履歴テーブルをカスタマイズできるのは、初回移行の適用前のみであることを承知しておいてください。 では、コードを見てみましょう。

まず、System.Data.Entity.Migrations.History.HistoryContext クラスから派生したクラスを作成する必要があります。 HistoryContext クラスは DbContext クラスから派生しているため、移行履歴テーブルの構成は、fluent API を使用して EF のモデルを構成することとよく似ています。 必要な作業は、OnModelCreating メソッドをオーバーライドし、fluent API を使用してテーブルを構成するだけです。

Note

通常、EF のモデルを構成する際に、オーバーライドした OnModelCreating メソッドから base.OnModelCreating() を呼び出す必要はありません。DbContext.OnModelCreating() の本体は空であるためです。 これは、移行履歴テーブルを構成する場合には当てはまりません。 この場合、OnModelCreating() のオーバーライド内で最初に行うべきことは、実際、base.OnModelCreating() を呼び出すことです。 そうすることで移行履歴テーブルが既定の方法で構成され、その後、オーバーライド メソッドで調整を行うことになります。

たとえば、移行履歴テーブルの名前を変更し、それを "admin" というカスタム スキーマに伝えたいとしましょう。 さらに、MigrationId 列の名前を Migration_ID に変更するよう同僚の DBA から依頼されています。  これを実現するためには、HistoryContext から派生した次のクラスを作成します。

    using System.Data.Common;
    using System.Data.Entity;
    using System.Data.Entity.Migrations.History;

    namespace CustomizableMigrationsHistoryTableSample
    {
        public class MyHistoryContext : HistoryContext
        {
            public MyHistoryContext(DbConnection dbConnection, string defaultSchema)
                : base(dbConnection, defaultSchema)
            {
            }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Entity<HistoryRow>().ToTable(tableName: "MigrationHistory", schemaName: "admin");
                modelBuilder.Entity<HistoryRow>().Property(p => p.MigrationId).HasColumnName("Migration_ID");
            }
        }
    }

カスタム HistoryContext が完成したら、コードベースの構成を用いてそれを登録し、カスタム HistoryContext を EF に認識させる必要があります。

    using System.Data.Entity;

    namespace CustomizableMigrationsHistoryTableSample
    {
        public class ModelConfiguration : DbConfiguration
        {
            public ModelConfiguration()
            {
                this.SetHistoryContext("System.Data.SqlClient",
                    (connection, defaultSchema) => new MyHistoryContext(connection, defaultSchema));
            }
        }
    }

これで終わりです。 後は、パッケージ マネージャー コンソールに移動し、Enable-Migrations、Add-Migration、Update-Database を順に実行してください。 これでデータベースへの追加が実行され、HistoryContext 派生クラスに記述した内容に従って移行履歴テーブルが構成されます。

Migrations History Table