次の方法で共有


既存データベースでのCode First Migrations

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

この記事では、Entity Framework で作成されていない既存のデータベースで Code First Migrations を使用する方法について説明します。

この記事では、基本的なシナリオで Code First Migrations を使用する方法について説明します。 そうでない場合は、続行する前に Code First Migrations を読む必要があります。

手順 1: モデルを作成する

最初の手順では、既存のデータベースを対象とする Code First モデルを作成します。 「 既存のデータベースに対するコードファースト 」トピックでは、これを行う方法に関する詳細なガイダンスを提供します。

データベース スキーマを変更する必要があるモデルに変更を加える前に、このトピックの残りの手順に従ってください。 次の手順では、モデルがデータベース スキーマと同期している必要があります。

手順 2: 移行を有効にする

次の手順では、移行を有効にします。 これを行うには、パッケージ マネージャー コンソールで Enable-Migrations コマンドを実行します。

このコマンドを実行すると、ソリューションに Migrations という名前のフォルダーが作成され、その中に Configuration という名前のクラスが 1 つ配置されます。 Configuration クラスでは、アプリケーションの移行を構成します。詳細については、「 Code First Migrations 」トピックを参照してください。

手順 3: 初期移行を追加する

移行が作成され、ローカル データベースに適用されたら、これらの変更を他のデータベースに適用することもできます。 たとえば、ローカル データベースがテスト データベースであり、最終的には、実稼働データベースや他の開発者のテスト データベースにも変更を適用する必要がある場合があります。 この手順には 2 つのオプションがあり、選択する必要があるオプションは、他のデータベースのスキーマが空であるか、現在ローカル データベースのスキーマと一致しているかによって異なります。

  • オプション 1: 開始点として既存のスキーマを使用します。 この方法は、移行が今後適用される他のデータベースが現在のローカル データベースと同じスキーマを持つ場合に使用する必要があります。 たとえば、ローカル テスト データベースが現在運用データベースの v1 と一致し、後でこれらの移行を適用して運用データベースを v2 に更新する場合に、これを使用できます。
  • オプション 2: 開始点として空のデータベースを使用します。 移行が今後適用される他のデータベースが空の場合 (またはまだ存在しない) 場合は、この方法を使用する必要があります。 たとえば、テスト データベースを使用してアプリケーションの開発を開始したが、移行を使用せずに、後で運用データベースを最初から作成する場合に、これを使用できます。

オプション 1: 既存のスキーマを開始点として使用する

Code First Migrations では、最新の移行に格納されているモデルのスナップショットを使用して、モデルへの変更を検出します (これについての詳細については、 Team Environment の Code First Migrations を参照してください)。 データベースに現在のモデルのスキーマが既に存在することを前提としているため、現在のモデルをスナップショットとして持つ空の (no-op) 移行を生成します。

  1. パッケージ マネージャー コンソールで Add-Migration InitialCreate –IgnoreChanges コマンドを実行します。 これにより、現在のモデルをスナップショットとして利用して、空のマイグレーションが生成されます。
  2. パッケージ マネージャー コンソールで Update-Database コマンドを実行します。 これにより、InitialCreate の移行がデータベースに適用されます。 実際の移行には変更が含まれていないため、この移行が既に適用されていることを示す行が __MigrationsHistory テーブルに追加されます。

オプション 2: 開始点として空のデータベースを使用する

このシナリオでは、ローカル データベースに既に存在するテーブルを含め、データベース全体を最初から作成できるように移行が必要です。 既存のスキーマを作成するロジックを含む InitialCreate 移行を生成します。 次に、既存のデータベースを、この移行が既に適用されたように見せていきます。

  1. パッケージ マネージャー コンソールで Add-Migration InitialCreate コマンドを実行します。 これにより、既存のスキーマを作成するための移行が作成されます。
  2. 新しく作成された移行の Up メソッド内のすべてのコードをコメント アウトします。 これにより、既に存在するすべてのテーブルなどを再作成せずに、ローカル データベースへの移行を "適用" できます。
  3. パッケージ マネージャー コンソールで Update-Database コマンドを実行します。 これにより、InitialCreate の移行がデータベースに適用されます。 実際の移行には変更が含まれていないため (一時的にコメント アウトしたため)、この移行が既に適用されていることを示す行が __MigrationsHistory テーブルに追加されます。
  4. Up メソッドでコードのコメントを解除します。 つまり、この移行が将来のデータベースに適用されると、ローカル データベースに既に存在していたスキーマが移行によって作成されます。

注意すべき事項

既存のデータベースに対して移行を使用する場合に注意する必要がある点がいくつかあります。

既定または計算された名前が既存のスキーマと一致しない可能性がある

移行では、マイグレーションを生成するときに、列とテーブルの名前を明示的に指定します。 ただし、移行を適用するときに既定の名前を計算するデータベース オブジェクトは他にもあります。 これには、インデックスと外部キー制約が含まれます。 既存のスキーマを対象とする場合、これらの計算された名前は、実際にデータベースに存在する名前と一致しない可能性があります。

これを認識する必要がある場合の例を次に示します。

手順 3 で "オプション 1: 既存のスキーマを開始点として使用する" を使用した場合:

  • モデルの今後の変更で、名前が異なるデータベース オブジェクトの 1 つを変更または削除する必要がある場合は、スキャフォールディングされた移行を変更して正しい名前を指定する必要があります。 Migrations API には、これを実行できる省略可能な Name パラメーターがあります。 たとえば、既存のスキーマに、IndexFk_BlogIdという名前のインデックスを持つ BlogId 外部キー列を持つ Post テーブルがあるとします。 ただし、既定では、移行では、このインデックスに IX_BlogId という名前が付けられます。 このインデックスを削除するモデルに変更を加えた場合は、スキャフォールディングされた DropIndex 呼び出しを変更して、IndexFk_BlogId名を指定する必要があります。

手順 3 で "オプション 2: 空のデータベースを開始点として使用する" を使用した場合:

  • 最初の移行のDownメソッドをローカルデータベースに対して実行しようとすると(つまり、データベースを空に戻す場合)、Migrationsが誤ったインデックス名や外部キー制約名を使ってそれらを削除しようとするため、失敗する可能性があります。 これは、最初の移行の Up メソッドを使用して他のデータベースが最初から作成されるため、ローカル データベースにのみ影響します。 既存のローカル データベースを空の状態にダウングレードする場合は、データベースを削除するか、すべてのテーブルを削除して手動で行うのが最も簡単です。 この最初のダウングレード後、すべてのデータベース オブジェクトは既定の名前で再作成されるため、この問題は再び発生しません。
  • モデルの今後の変更で、名前が異なるデータベース オブジェクトの 1 つを変更または削除する必要がある場合、名前が既定値と一致しないため、既存のローカル データベースに対してこの操作は機能しません。 ただし、移行によって選択された既定の名前が使用されるため、"ゼロから" 作成されたデータベースに対して機能します。 これらの変更は、ローカルの既存のデータベースで手動で行うか、他のマシンと同様に、移行によってデータベースをゼロから再作成することを検討できます。
  • 最初の移行の Up メソッドを使用して作成されたデータベースは、インデックスと外部キー制約の計算された既定の名前が使用されるため、ローカル データベースとは若干異なる場合があります。 移行では既定で外部キー列にインデックスが作成されるため、最終的には追加のインデックスが作成される可能性があります。元のローカル データベースではそうではない可能性があります。

すべてのデータベース オブジェクトがモデルで表されるわけではありません

モデルに含まれていないデータベース オブジェクトは、移行では処理されません。 これには、ビュー、ストアド プロシージャ、アクセス許可、モデルに含まれていないテーブル、追加のインデックスなどが含まれます。

これを認識する必要がある場合の例を次に示します。

  • '手順 3' で選択したオプションに関係なく、モデルの将来の変更でこれらの追加オブジェクトの変更または削除が必要な場合、移行はこれらの変更を行う必要はありません。 たとえば、追加のインデックスがある列を削除した場合、Migrations はインデックスを削除する必要はありません。 これをスキャフォールディングされた移行に手動で追加する必要があります。
  • "オプション 2: 空のデータベースを開始点として使用する" を使用した場合、これらの追加オブジェクトは初期移行の Up メソッドでは作成されません。 必要に応じて、これらの追加オブジェクトを管理するように Up メソッドと Down メソッドを変更できます。 ビューなど、Migrations API でネイティブにサポートされていないオブジェクトの場合は、 Sql メソッドを使用して生の SQL を実行して作成/削除できます。