EntityFrameworkで1対多のリレーションシップを定義してみます。
ソースコード
using Microsoft.EntityFrameworkCore;
using System.Dynamic;
using System.IO.Compression;
// グループエンティティクラス
public class Group
{
public int GroupID { get; set; } = 0;
public string GroupName { get; set; } = "";
// 1対多のリレーションシップ
public ICollection<User> Users { get; set; } = [];
}
// ユーザーエンティティクラス
public class User
{
public int UserID { get; set; } = 0;
public string Name { get; set; } = "";
// 外部キー
public int GroupID { get; set; } = 0;
// グループのプロパティ
public Group? Group { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<Group> Groups => Set<Group>();
public DbSet<User> Users => Set<User>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// SQLiteデータベースファイルのパスを指定
// アプリケーションの実行ディレクトリに MyDatabase.db が作成されます
optionsBuilder.UseSqlite("Data Source=MyDatabase.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Fluent API を使って1対多のリレーションシップを定義
modelBuilder.Entity<User>()
.HasOne(e => e.Group) // User は1つの Group を持つ
.WithMany(d => d.Users) // Group は複数の User を持つ
.HasForeignKey(e => e.GroupID) // User の GroupId が外部キー
.OnDelete(DeleteBehavior.Restrict); // Group が削除されても User は削除されないようにする
// 初期データの追加
modelBuilder.Entity<Group>().HasData(
new Group { GroupID = 1, GroupName = "Expert" },
new Group { GroupID = 2, GroupName = "Novice" }
);
modelBuilder.Entity<User>().HasData(
new User { UserID = 1, Name = "taro", GroupID = 1 },
new User { UserID = 2, Name = "hanako", GroupID = 2 },
new User { UserID = 3, Name = "jiro", GroupID = 2 }
);
}
}
class Program
{
static void Main()
{
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var context = new MyDbContext();
// テーブル作成
context.Database.EnsureCreated();
var users = context.Users.Include(d => d.Group).ToList();
foreach (var user in users)
{
if (user.Group is null)
{
Console.WriteLine($"{user.UserID} {user.Name} {user.GroupID}");
}
else
{
Console.WriteLine($"{user.UserID} {user.Name} {user.GroupID} {user.Group.GroupName}");
}
}
// 結果
// 1 taro 1 Expert
// 2 hanako 2 Novice
// 3 jiro 2 Novice
}
}
感想
Groupには複数のUserが所属し、Userは一つGroupに所属するという関係を表現しています。
Group.UsersがICollectionだったり、User.Groupがnull許容だったりと、データベースのテーブルの項目をC#のプロパティとしてアクセスするための間口が用意されています。
テーブル同士の関係性(リレーションシップ)はOnConfiguring()内でfluent APIにより行われています。詳しくはコメントに記述していますので割愛しますが、上手にSQLは隠蔽されていますが、SQLを知らない人間が見ると(筆者を含む)チンプンカンプンなのでは無いかと思います。
ただ、内容は理解していない場合でも、使い方さえ知っていれば役立てることが出来るので、頑張って学習しようと思います。
コメント