対象読者
Entity Framework Core を使った開発経験があり、既存のデータベースをマイグレーション管理下に置きたい方
はじめに
データベースの変更管理はアプリケーション開発のボトルネックになりがちですよね。
現代のアプリケーション開発では、このボトルネックを緩和するため、マイグレーションツールを採用するケースが多いと思います。
.NET では、Entity Framework Core(以下 EF Core)にマイグレーション機能が用意されています。
マイグレーションを採用すると、主に以下のようなメリットが得られます。
- コード変更とスキーマ変更が同期するため、コード上のクラスとデータベースの DDL を二重管理しなくてよい
- スキーマ変更の履歴が差分として残るため、差分適用やロールバックが容易
- 開発者の開発環境や検証環境で個別に DDL を実行する必要がなくなるため、データベースの状態を統一しやすい
このようなメリットを享受するため、まだマイグレーション管理していない運用中のデータベースに対して、新たにマイグレーション対象としたいケースがあります。
本記事では、まず前提知識として EF Core の基本についてお伝えし、続いて本題の 運用中のデータベースを EF Core のマイグレーション管理下にする方法 をお伝えします。
本記事執筆時点(2025年12月)において、本手順の EF Core における公式手順が存在しないため、EF Core ユーザーにとってご参考になればと思います。
[補足]
本手順に関連するマイクロソフト公式情報として、Entity Framework 6 (.NET Framework 時代の ORM) での手順が公開されています。既存のデータベースに Code First Migrations を使用する
この手順では
Add-Migration InitialCreate –IgnoreChangesコマンドで空のマイグレーションを作成しつつ現在のモデルスナップショットを作成する操作が含まれます。しかしながら、EF Core の CLI では該当コマンドが存在しないため、同手順を実施することはできません。
本記事では対象データベースを SQL Server / SQL Database 前提に記載しています。
他のデータベース製品でも同様の手順を適用可能と思われますが、実施する際は必ずお手元の環境で検証をお願いします。
また、本番データベースで作業する場合は必ずバックアップを取得し、復元できる状態にしてから実施してください。
EF Core とマイグレーションの概要
EF Core
EF Core は ORM(Object Relational Mapper)として、C# のクラスとデータベースのテーブルをマッピングする役割を担います。
例えば以下のような C# のクラスを定義します(このようなクラスをエンティティクラスと呼びます)。
// Userクラスの例
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
するとデータベース上では以下のようなテーブルとマッピングされることになります。
-- Usersテーブルの例
CREATE TABLE Users (
Id INT NOT NULL PRIMARY KEY,
Name NVARCHAR(MAX) NOT NULL,
Email NVARCHAR(MAX) NOT NULL
);
このマッピングにより、開発者はデータベースのテーブルを意識せず、C# のオブジェクトを操作する感覚でデータアクセスができます。
例えば Users テーブルからユーザー一覧を取得する場合でも、SQL を直接記述する必要はなく、次のように記述できます。
var users = dbContext.Users.ToList();
また、新しいユーザーを追加する場合も、クラスのインスタンスを生成して登録するだけです。
dbContext.Users.Add(new User
{
Name = "Taro",
Email = "taro@example.com"
});
dbContext.SaveChanges();
EF Core マイグレーション
EF Core では、C# のエンティティクラスとデータベース構造の対応関係を管理する仕組みとして マイグレーション(Migration) という機能が用意されています。
マイグレーションを利用すると、エンティティクラスの変更を元に、データベースのスキーマ変更を安全に反映できます。
例えば、先ほどの User クラスに Age を追加したとします。
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
この変更をデータベースに反映するには、次のコマンドを実行します。
dotnet ef migrations add <マイグレーション名>
すると、変更内容を表すマイグレーションファイルが自動生成されます。
その後、以下のコマンドを実行することでデータベースが更新されます。
dotnet ef database update
結果、開発環境・テスト環境・本番環境、すべて同じ手順でデータベース構造を揃えること が可能になります。
コードファーストと DB ファースト
上述したマイグレーションの仕組みは C# のコードを正とする、いわゆる コードファースト と呼ばれる仕組みです。
一方で、データベースの状態を正として C# のコードを反映する DB ファースト という仕組みもあります。
DB ファーストは、対象データベースのスキーマ(テーブル/カラム/キー/インデックス等)を元に、対応する C# のエンティティクラスや DbContext を作成することができます。
この仕組みを スキャフォールディング と言います。
しかしながら、DB ファーストは EF Core のマイグレーション管理用途には基本的に向いていません。
EF Core のマイグレーションは、「現在の C# のエンティティモデル」と「前回マイグレーション時点のモデルスナップショット」 を比較し、その差分をもとにデータベーススキーマを更新する仕組みです。
一方、DB ファーストではスキーマ変更がデータベース側で先に行われます。
この変更内容は EF Core のモデルスナップショットには反映されないため、差分として検知できず、マイグレーション管理が破綻しやすくなります。
ここまで、EF Core の基本的な機能概要をお伝えしました。
以降、本題となる「運用中のデータベースを EF Core マイグレーション対象とする方法」について説明します。
運用中のデータベースを EF Core マイグレーション対象とする方法
運用中のデータベース、つまりすでにスキーマが存在するデータベースを新たに EF Core マイグレーション管理対象とするには、大きく分けて以下の手順を実施します。
- 運用中のデータベースから、スキャフォールディングでエンティティクラスおよび DbContext を生成する
- 生成されたエンティティクラスと DbContext を元に、初期マイグレーションを作成する
- 運用中のデータベースに、初期マイグレーションが適用済みであることをマークする
実際の手順をステップごとに説明します。
1. スキャフォールディングでエンティティクラスを生成する
まず、運用中の SQL Database のスキーマを元に、開発環境でエンティティクラスを生成します。
以下はコマンドの例です。
dotnet ef dbcontext scaffold <DB接続文字列> Microsoft.EntityFrameworkCore.SqlServer -o <エンティティクラスの出力先ディレクトリ名> -c <生成するDbContextの名前> --context-dir <DbContextファイルを格納するディレクトリ>
※ コマンドオプションの詳細は公式ドキュメントを参照してください。
これにより、指定したディレクトリにエンティティクラス群と DbContext ファイルが出力されます。
なお、スキャフォールディングされた結果について、意図通りのスキーマになっていることを必ずレビューしてください。
2. 初期マイグレーションを作成する
スキャフォールディングで生成したモデルをもとに、初期マイグレーションを作成します。
dotnet ef migrations add <マイグレーション名>
3. 運用中のデータベースに、初期マイグレーションが適用済みであることをマークする
- で生成されたマイグレーションは、運用中のデータベースに既に存在するテーブルを 新規作成する 内容になっています。
そのため、この初期マイグレーションは運用中のデータベースに適用してはいけません。
※1 運用中のデータベースに対して初期マイグレーションを適用すると、既存テーブルとの競合エラーや意図しないスキーマ変更が発生する可能性があるため、絶対に実行しないでください。
※2 初期マイグレーション作成後にエンティティクラスを変更しないでください。変更すると、データベースとエンティティの差分が正しく認識されなくなります。
一方で、運用中のデータベースには「このデータベースはマイグレーション対象であること」と「初期マイグレーションが適用済みであること」を知らせる必要があります。
EF Core では、マイグレーションを __EFMigrationsHistory テーブルで管理しています。
__EFMigrationsHistory テーブルに初期マイグレーションのレコードを INSERT することで、このデータベースがマイグレーション対象であり、初期マイグレーションが適用済みであることを知らせることができます。
以下は具体的な手順です。
まず、作成した初期マイグレーションの MigrationId と ProductVersion を調べます(後で利用するため記録しておきます)。
-
MigrationId
以下のコマンドでMigrationIdの一覧が取得できます(Migrationsディレクトリに格納されるマイグレーションファイル名(拡張子なし)と同一です)。dotnet ef migrations list -
ProductVersion
初期マイグレーション作成時点での EF Core のバージョンです。
対象プロジェクトの.csprojファイルでMicrosoft.EntityFrameworkCoreのバージョンを確認してください。(以下例の場合、”9.0.3”)<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
次に、運用中のデータベースに対して以下の操作を行います。
-
__EFMigrationsHistoryテーブルを作成 - 初期マイグレーションの
MigrationIdとProductVersionを値とするレコードを INSERT する
SQL の例:
-- __EFMigrationsHistory テーブルを作成
CREATE TABLE [dbo].[__EFMigrationsHistory] (
[MigrationId] NVARCHAR(150) NOT NULL,
[ProductVersion] NVARCHAR(32) NOT NULL,
CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
);
-- 初期マイグレーションのレコードを INSERT
INSERT INTO [dbo].[__EFMigrationsHistory]
([MigrationId], [ProductVersion])
VALUES
('<上記手順で記録したMigrationId>', '<上記手順で記録したProductVersion');
INSERT したデータの確認:
SELECT TOP (1000) * FROM [dbo].[__EFMigrationsHistory]
以上で EF Core は 「初期マイグレーションは既に適用済み」 と判断し、以後の差分マイグレーションのみ適用される状態になります。
マイグレーション対象とした後の運用
上記の手順以降、通常のコードファーストと同様にマイグレーション運用できます。
例えばエンティティクラスや DbContext に何らかの変更を行った場合、差分のマイグレーションファイルを作成します。
差分マイグレーションの作成
dotnet ef migrations add <マイグレーション名>
データベースへの適用
dotnet ef database update
これで差分がデータベースに反映されます。
念のため __EFMigrationsHistory テーブルを確認すると、差分のマイグレーションが適用されていることが確認できます。
SELECT TOP (1000) * FROM [dbo].[__EFMigrationsHistory]
まとめ
本記事では、運用中のデータベースを EF Core のマイグレーション管理対象にする方法を紹介しました。
EF Core のマイグレーションは、アプリケーション開発のボトルネックになりがちなデータベース環境管理にアジリティをもたらす便利な仕組みです。
新たにマイグレーションにチャレンジしたい方にとって、今回の手順が参考になると幸いです。
We Are Hiring!




