移行の適用

移行を追加したら、移行を展開してデータベースに適用する必要があります。 これを行うためのさまざまな戦略があります。一部は運用環境に適しており、その他のものは開発ライフサイクルに適しています。

Note

どの展開戦略であっても、必ず、生成された移行を検査およびテストしてから運用データベースに適用するようにしてください。 列の名前変更を意図していたが、移行で列が削除されたり、データベースに適用するときにさまざまな理由で失敗したりする場合があります。

SQL スクリプト

移行を運用データベースに展開するための推奨される方法は、SQL スクリプトの生成による方法です。 この戦略の利点は次のとおりです。

  • SQL スクリプトの正確性を審査することができます。スキーマ変更を運用データベースに適用することは、データ損失を伴う可能性のある危険な操作であるため、このことは重要です。
  • 場合によっては、運用データベースの特定のニーズに合わせてスクリプトを調整できます。
  • SQL スクリプトは展開テクノロジと組み合わせて使用でき、CI プロセスの一部として生成することもできます。
  • SQL スクリプトは DBA に提供でき、個別に管理およびアーカイブすることもできます。

基本的な使用

次の例では、空のデータベースから最新の移行への SQL スクリプトが生成されます。

dotnet ef migrations script

From を使用する (暗黙的な指定に対して)

次の例では、特定の移行から最新の移行への SQL スクリプトが生成されます。

dotnet ef migrations script AddNewTables

From および To を使用する

次の例では、指定された from の移行から指定された to の移行への SQL スクリプトが生成されます。

dotnet ef migrations script AddNewTables AddAuditTable

ロールバック スクリプトを生成するために、to より新しい from を使用することができます。

警告

データ損失の可能性のあるシナリオには注意してください。

スクリプト生成では、生成する必要がある移行の範囲を示す次の 2 つの引数を受け取ります。

  • from 移行は、スクリプトの実行前にデータベースに適用される最後の移行にする必要があります。 移行が適用されていない場合、0 を指定します (これは既定です)。
  • to 移行は、スクリプトの実行後にデータベースに適用される最後の移行です。 これは既定でプロジェクトの最後の移行になります。

べき等 SQL スクリプト

上記で生成される SQL スクリプトは、スキーマをある移行から別の移行に変更するためにのみ適用できます。スクリプトを適切に適用し、正しい移行状態のデータベースに対してのみ適用することは、ユーザーの責任です。 EF Core では、べき等スクリプトの生成もサポートしています。これは、既に適用されている移行を (移行履歴テーブルを使用して) 内部的に検査し、不足している移行のみを適用するものです。 これは、データベースに適用された最後の移行が正確にわからない場合、あるいは移行が異なる可能性がある複数のデータベースに展開する場合に便利です。

次の例では、べき等移行が生成されます。

dotnet ef migrations script --idempotent

コマンド ライン ツール

EF コマンド ライン ツールを使用して、データベースに移行を適用できます。 このアプローチは移行のローカル開発とテストでは生産性が高いですが、運用データベースの管理には最適ではありません。

  • SQL コマンドがツールによって直接適用され、開発者に検査や変更を行う機会がありません。 これは運用環境では危険な場合があります。
  • .NET SDK と EF ツールは運用サーバーにインストールする必要があり、プロジェクトのソース コードが必要です。

Note

各移行は、独自のトランザクションで適用されます。 この領域において将来可能性のある機能強化については、GitHub イシュー #22616 を参照してください。

次の例では、データベースを最新の移行に更新します。

dotnet ef database update

次の例では、データベースを特定の移行に更新します。

dotnet ef database update AddNewTables

以前の移行にロールバックするためにも使用できます。

警告

データ損失の可能性のあるシナリオには注意してください。

コマンド ライン ツールを使用して移行を適用する方法の詳細については、「EF Core ツールのリファレンス」を参照してください。

バンドル

移行バンドルは、データベースに移行を適用するために使用できる単一ファイルの実行可能ファイルです。 これらは、次のような SQL スクリプトとコマンドライン ツールの欠点の一部に対処します。

  • SQL スクリプトを実行するには、追加のツールが必要です。
  • これらのツールによるトランザクション処理とエラー時の続行動作には一貫性がなく、予期できない場合もあります。 そのため、移行の適用時にエラーが発生した場合に、データベースが未定義の状態になる可能性があります。
  • バンドルは、CI プロセスの一部として生成することができ、後で配置プロセスの一部として簡単に実行することができます。
  • バンドルは、.NET SDK または EF ツールを (または、自己完結型の場合は .NET ランタイムさえも) インストールせずに実行でき、プロジェクトのソース コードは必要ありません。

以下により、バンドルが生成されます。

dotnet ef migrations bundle

以下により、Linux 用の自己完結型バンドルが生成されます。

dotnet ef migrations bundle --self-contained -r linux-x64

バンドルの作成の詳細については、「EF Core ツールのリファレンス」を参照してください。

efbundle

生成される実行可能ファイルは、既定では efbundle という名前になります。 これは、データベースを最新の移行に更新するために使用できます。 これは、dotnet ef database update または Update-Database を実行するのと同等です。

引数:

引数 説明
<MIGRATION> ターゲット移行。 '0' の場合、すべての移行が元に戻されます。 既定値は、最後の移行です。

"オプション:

オプション Short 説明
--connection <CONNECTION> データベースへの接続文字列。 既定値は、AddDbContext または OnConfiguring で指定された文字列です。
--verbose -v 詳細出力を表示します。
--no-color 出力を色分けしません。
--prefix-output レベルを含むプレフィックス出力。

次の例では、指定したユーザー名とパスワードを使用して、ローカル SQL Server インスタンスに移行を適用します。

.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password=myPassword'

警告

appsettings.json をバンドルと一緒にコピーすることを忘れないでください。 バンドルは、実行ディレクトリの appsettings.json の存在に依存します。

移行バンドルの例

バンドルには、組み込む移行が必要です。 これらは、「最初の移行を作成する」で説明されているように、dotnet ef migrations add を使用して作成されます。 移行を展開する準備ができたら、dotnet ef migrations bundle を使用してバンドルを作成します。 次に例を示します。

PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>

出力は、対象のオペレーティング システムに適した実行可能ファイルです。 この場合、これは Windows x64 であるため、efbundle.exe はローカル フォルダーに作成されます。 この実行可能ファイルを実行すると、その中に含まれる移行が適用されます。

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903083845_MyMigration'.
Done.
PS C:\local\AllTogetherNow\SixOh>

dotnet ef database updateUpdate-Database と同様に、移行は、まだ適用されていない場合にのみ、データベースに適用されます。 たとえば、同じバンドルを再度実行しても、適用する新しい移行がないため、何も行われません。

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
No migrations were applied. The database is already up to date.
Done.
PS C:\local\AllTogetherNow\SixOh>

ただし、モデルを変更し、dotnet ef migrations add を使用してさらに移行を生成した場合は、適用できる状態の新しい実行可能ファイルにそれらをバンドルできます。 次に例を示します。

PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add SecondMigration
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add Number3
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle --force
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>

ヒント

--force オプションを使用すると、既存のバンドルを新しいバンドルで上書きできます。

この新しいバンドルを実行すると、これら 2 つの新しい移行がデータベースに適用されます。

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>

既定では、バンドルで使用されるデータベース接続文字列は、アプリケーションの構成から取得されます。 ただし、コマンド ラインで接続文字列を渡すことにより、別のデータベースを移行できます。 次に例を示します。

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe --connection "Data Source=(LocalDb)\MSSQLLocalDB;Database=SixOhProduction"
Applying migration '20210903083845_MyMigration'.
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>

Note

ここでは、3 つの移行がすべて適用されました。これは、これらのいずれもまだ、運用データベースに適用されていなかったためです。


実行時に移行を適用する

アプリケーション自体が、通常は起動時にプログラムによって移行を適用することができます。 このアプローチは移行のローカル開発とテストでは生産性が高いですが、次の理由から運用データベースの管理には適していません。

  • アプリケーションの複数のインスタンスが実行されている場合、両方のアプリケーションによって移行を同時に適用しようとして失敗する (または悪い場合はデータの破損を引き起こす) 可能性があります。
  • 同様に、アプリケーションが移行している間に別のアプリケーションがデータベースにアクセスした場合、重大な問題が発生する可能性があります。
  • アプリケーションに、データベース スキーマを変更するための昇格されたアクセス権が必要です。 一般に、アプリケーションのデータベース アクセス許可を運用環境で制限することが推奨されています。
  • 問題が発生した場合、適用された移行をロールバックできる必要があります。 他の戦略では、これを簡単かつすぐに実行できます。
  • SQL コマンドがプログラムによって直接適用され、開発者に検査や変更を行う機会がありません。 これは運用環境では危険な場合があります。

移行をプログラムで適用するには、context.Database.Migrate() を呼び出します。 たとえば、一般的な ASP.NET アプリケーションでは、次の操作を実行できます。

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    using (var scope = host.Services.CreateScope())
    {
        var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        db.Database.Migrate();
    }

    host.Run();
}

Migrate() は、より高度なシナリオで利用される IMigrator サービスの上にビルドされます。 アクセスするには myDbContext.GetInfrastructure().GetService<IMigrator>() を利用します。

警告

  • このアプローチを運用環境で使用する前に、慎重に検討してください。 経験から、この展開戦略の簡単さよりも、発生する問題の方が上回っています。 代わりに、移行から SQL スクリプトを生成することを検討してください。
  • Migrate() の前に EnsureCreated() を呼び出さないでください。 EnsureCreated() は移行をバイパスしてスキーマを作成し、Migrate() が失敗します。