データベース設計において「ユーザー(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が同時に保存され、外部キーも正しく設定される
}
