【C#】Entity Framework Coreでテーブル間のリレーション(1対多)を定義する

データベース設計において「ユーザー(1) 対 投稿(多)」のような関係性は非常に一般的です。 Entity Framework Core (EF Core) では、クラス間にナビゲーションプロパティ(相手のクラスを参照するプロパティ)を定義することで、自動的にリレーションと外部キー制約を作成してくれます。

目次

実装サンプル:UserとPostの1対多関係

以下のコードでは、1人の User が複数の Post を持ち、それぞれの Post は必ず1人の User に属する関係を定義しています。

Model.cs

using System;
using System.Collections.Generic; // ICollectionを使うために必要

public class User
{
    // 主キー
    public int UserId { get; set; }

    public string Name { get; set; }
    public string Email { get; set; }

    // 【親側の設定】
    // 1人のユーザーは複数の投稿を持つため、コレクション(リスト)で定義します。
    // これを「コレクション ナビゲーション プロパティ」と呼びます。
    public ICollection<Post> Posts { get; set; } = new List<Post>();
}

public class Post
{
    // 主キー
    public int PostId { get; set; }

    public string Message { get; set; }
    public DateTime SentTime { get; set; }

    // 【外部キー (Foreign Key)】
    // 命名規則「参照クラス名 + Id」に従うと、自動的に外部キーとして認識されます。
    public int UserId { get; set; }

    // 【子側の設定】
    // この投稿がどのユーザーに属するかを表します。
    // これを「参照ナビゲーション プロパティ」と呼びます。
    public User User { get; set; }
}

ExampleDbContext.cs

リレーションを持つモデルを DbContext に追加します。通常、親側(User)と子側(Post)の両方を DbSet に記述しますが、親側だけでもリレーションを辿って認識されることはあります。

using Microsoft.EntityFrameworkCore;

public class ExampleDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseSqlite("Data Source=example.db");

    public DbSet<User> Users { get; set; }
    public DbSet<Post> Posts { get; set; }
}

解説とポイント

1. ナビゲーションプロパティ

  • Userクラス側: public ICollection<Post> Posts { get; set; }
    • ユーザーから見て「自分の投稿一覧」にアクセスするためのプロパティです。
  • Postクラス側: public User User { get; set; }
    • 投稿から見て「投稿主」にアクセスするためのプロパティです。

2. 外部キーの命名規則

EF Core の規約では、以下の形式のプロパティが自動的に外部キー(Foreign Key)として認識されます。

  • NavigationPropertyName + PrincipalKeyPropertyName (例: UserId)
  • PrincipalClassName + PrincipalKeyPropertyName (例: UserId)
  • PrincipalKeyPropertyName (例: Id ※単独の場合)

今回の例では、User クラスの主キーが UserId であり、Post クラスにも UserId というプロパティがあるため、これらが自動的に紐付けられます。

3. データの保存例

リレーションが定義されていると、オブジェクトの親子関係を保ったまま保存が可能です。

C#

using (var db = new ExampleDbContext())
{
    var user = new User { Name = "Gihyo Taro", Email = "taro@example.com" };
    
    // UserのPostsコレクションにPostを追加するだけで、UserIdが自動設定されます
    user.Posts.Add(new Post { Message = "Hello EF Core!", SentTime = DateTime.Now });
    user.Posts.Add(new Post { Message = "Second post.", SentTime = DateTime.Now });

    db.Users.Add(user);
    db.SaveChanges(); // Userと2つのPostが同時に保存され、外部キーも正しく設定される
}
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次