Entity Framework Core の Migration とプロジェクト構成(コードファースト)

July 6, 2025 7:5

基本的なプロジェクト構成

(a) ○○○.Web(Webアプリケーション)

  • スタートアッププロジェクト
  • Pages/Views(*.cshtml)
  • ViewModels(*.cs)
  • Controllers(*.cs)
  • Program.cs(DbContext の追加)
  • appsettings.json(接続文字列の追加)

例)DbContext の追加

Program.cs
var builder = WebApplication.CreateBuilder(args);

// DbContext の追加
builder.Services.AddDbContext<DefaultDataContext>(options =>
{
    options.UseNpgsql(builder.Configuration.GetDefaultConnectionString());
    options.EnableSensitiveDataLogging();
});

// Add services to the container.
builder.Services.AddRazorPages();

例)接続文字列

// appsettings.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=localhost;Database=timecard;Username=postgres;Password=hoge;Port=5432"
  },

(b) ○○○.DataAccess(データアクセス用ライブラリ)

  • Migrations(*.cs)自動生成
  • ○○○DataContext.cs
  • ○○○DataContext.DbSet.cs
  • ○○○DataContext.OnModelCreating.cs

例)DefaultDataContext(PostgreSQL)

// DefaultDataContext.cs
public partial class DefaultDataContext : DbContext
{
    public DefaultDataContext(DbContextOptions options)
        : base(options)
    {
        AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
    }
}

// DefaultDataContext.DbSet.cs
public partial class DefaultDataContext
{
    public DbSet<User> User { get; set; }
    public DbSet<UserCard> UserCard { get; set; }
    public DbSet<TimeCard> TimeCard { get; set; }
}

// DefaultDataContext.OnModelCreating.cs
public partial class DefaultDataContext
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<User>(e => { e.HasKey(e => new { e.UserId }); });
        builder.Entity<UserCard>(e => { e.HasKey(e => new { e.UserId, e.CardNumber }); });
        builder.Entity<TimeCard>(e => { e.HasKey(e => new { e.UserId, e.Date }); });

        // 名称をSnakeCaseに変換
        builder.ToSnakeNames();
    }
}

(c) ○○○.Common(モデル(≒DBテーブル)定義) ・Models(*.cs)

##プロジェクトの依存関係 (a) ⇒ (b)、(c) (b) ⇒ (c)

(a) ○○○.Web(Webアプリケーション)は MVVM パターンのView、ViewModel を実装。
Razor Pages を使用する場合は、半強制的に View、ViewModel の形式となる。
MVC の場合は View と1対1で対応するように ViewModel を作成する。

(c) ○○○.Common(モデル定義)はMVVMパターンの Model を実装。
1テーブル = 1クラスとなるように実装。

ViewModel :画面表示項目のデータ定義
Model:DBのテーブル定義
上記のように役割を完全に分離させる。
依存関係を (a) ⇒ (b)、(c) とすることで、画面表示の仕様変更があっても、DBのテーブル定義が直接影響を受けないようにすることがポイント。

##各プロジェクトに最低限必要なパッケージ

(a) ○○○.Web(Webアプリケーション)
Microsoft.EntityFrameworkCore.Design

(b) ○○○.DataAccess(データアクセス用ライブラリ)
Microsoft.EntityFrameworkCore.Tools
データベースプロバイダ(使用するデータベースに応じて選択)

  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Sqlite
  • Npgsql.EntityFrameworkCore.PostgreSQL
  • Oracle.EntityFrameworkCore

(c) ○○○.Common(モデル定義)
なし
(b) と (c) を分離することによって、特定のデータベースに依存しないモデル(テーブル)定義が可能になる。

Migration の実行

(1) モデルの新規作成/修正
(2) ソリューションのビルド
(3) パッケージマネージャーコンソールを表示
(4) 「既定のプロジェクト」に「○○○.DataAccess」が選択されていることを確認
(5) 以下のコマンドを実行

Add-Migration 移行の名前

「移行の名前」は任意だが、一意である必要がある。
(モデルの変更をデータベースに適用する毎に Add-Migration を実行することになるが、同じ「移行の名前」は複数回使えない)
このタイミングで ○○○.DataAccess/Migrations フォルダに変更内容を定義した *.cs ファイルが作成される。

(6) 以下のコマンドを実行

Update-Database

このタイミングでモデルの変更がデータベースに適用される。