bucket-sort logo bucket-sort

プログラミングとインフラエンジニアリングの覚え書き

  • Posts
  • About
  • Contact
  1. Home
  2. All Posts
  3. [C#] EF Core の基本部品を理解する

[C#] EF Core の基本部品を理解する

Jul 26, 2026 C# , .NET , Entity Framework Core bucket-sort

前回は、Entity Framework Core の役割と ADO.NET との違いを見ました。

今回は、EF Core の基本部品を整理します。
特に重要なのは、DbContext、DbSet<T>、変更追跡、エンティティです。

DbContext は作業単位

DbContext は、EF Core におけるデータベース操作の中心です。

役割は大きく分けて次の通りです。

  • データベース接続の設定を持つ
  • モデルとテーブルの対応付けを管理する
  • クエリを実行する
  • 取得したオブジェクトの変更を追跡する
  • SaveChanges() で変更を保存する
using Microsoft.EntityFrameworkCore;

public sealed class AutoLotContext : DbContext
{
    public AutoLotContext(DbContextOptions<AutoLotContext> options)
        : base(options)
    {
    }

    public DbSet<Car> Cars => Set<Car>();
    public DbSet<Order> Orders => Set<Order>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Car>().ToTable("Inventory");
        modelBuilder.Entity<Order>().ToTable("Orders");
    }
}

DbContext は長く使い回すものではありません。
Web アプリでは 1 リクエストごと、コンソールアプリでは 1 つの作業単位ごとに作る、と考えると扱いやすいです。

DbSet はテーブルに対応する入口

DbSet<T> は、特定のエンティティ型の集合を表します。

public DbSet<Car> Cars => Set<Car>();

Cars に対して LINQ を書くと、EF Core が SQL に変換します。

List<Car> hondas = await context.Cars
    .Where(car => car.Make == "Honda")
    .ToListAsync();

追加、更新、削除の入口にもなります。

context.Cars.Add(new Car
{
    Make = "Honda",
    Color = "Blue",
    PetName = "Vega"
});

await context.SaveChangesAsync();

DbSet<T> は、テーブルそのものというより「その型を問い合わせたり変更したりする入口」と考えると自然です。

エンティティとは

EF Core でデータベースの行に対応するクラスを、エンティティと呼びます。

public sealed class Car
{
    public int Id { get; set; }
    public string Make { get; set; } = "";
    public string Color { get; set; } = "";
    public string PetName { get; set; } = "";

    public List<Order> Orders { get; set; } = new();
}

注文を表すエンティティです。

public sealed class Order
{
    public int Id { get; set; }
    public int CarId { get; set; }
    public string CustomerName { get; set; } = "";
    public DateTime OrderDate { get; set; }

    public Car? Car { get; set; }
}

CarId は外部キーです。
Car はナビゲーションプロパティです。

リレーション設定です。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Car>()
        .ToTable("Inventory")
        .HasMany(car => car.Orders)
        .WithOne(order => order.Car)
        .HasForeignKey(order => order.CarId);
}

変更追跡の考え方

EF Core は、取得したエンティティの状態を追跡します。

Car? car = await context.Cars.FindAsync(1);

if (car != null)
{
    car.PetName = "New Name";
    await context.SaveChangesAsync();
}

このコードでは、Update 文を明示的に書いていません。
EF Core が car.PetName の変更を検知し、SaveChangesAsync() 時に必要な SQL を発行します。

ChangeTracker で状態を見る

ChangeTracker を使うと、EF Core が追跡しているエンティティ状態を確認できます。

Car car = new Car
{
    Make = "Toyota",
    Color = "Black",
    PetName = "Night"
};

context.Cars.Add(car);

foreach (var entry in context.ChangeTracker.Entries())
{
    Console.WriteLine($"{entry.Entity.GetType().Name}: {entry.State}");
}

代表的な状態は次の通りです。

Added

新規追加され、まだデータベースへ保存されていない状態です。

Unchanged

データベースから取得され、変更されていない状態です。

Modified

取得後に変更された状態です。

Deleted

削除予定の状態です。

Detached

コンテキストに追跡されていない状態です。

状態を理解すると、SaveChanges() が何を実行するのか見通しやすくなります。

所有される型

エンティティとして独立させるほどではない値のまとまりを、所有される型として扱えます。

public sealed class Customer
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public Address Address { get; set; } = new();
}

public sealed class Address
{
    public string PostalCode { get; set; } = "";
    public string City { get; set; } = "";
    public string Street { get; set; } = "";
}

設定です。

modelBuilder.Entity<Customer>()
    .OwnsOne(customer => customer.Address);

Address は単独の主キーを持つ独立エンティティではなく、Customer に所有される値として扱われます。

住所、金額、期間、座標など、値オブジェクト的なものに向いています。

キーなし型

主キーを持たない読み取り専用の結果を扱いたい場合、キーなし型を使えます。

public sealed class InventorySummary
{
    public string Make { get; set; } = "";
    public int Count { get; set; }
}

設定です。

modelBuilder.Entity<InventorySummary>()
    .HasNoKey()
    .ToView(null);

生 SQL やビューの結果を受け取る用途に向いています。

List<InventorySummary> summaries = await context
    .Set<InventorySummary>()
    .FromSqlRaw("""
        SELECT Make, COUNT(*) AS Count
        FROM Inventory
        GROUP BY Make
        """)
    .ToListAsync();

キーなし型は変更追跡や更新対象には向きません。
集計結果やレポート用の読み取りモデルとして考えると分かりやすいです。

DbContext の寿命に注意する

DbContext は軽量な作業単位として扱います。
長く持ち続けると、追跡対象が増えすぎたり、古いデータを保持したりします。

避けたい例です。

// アプリ全体で 1 つだけ使い回すのは避ける
static AutoLotContext SharedContext = ...;

おすすめは、必要な処理ごとに作って破棄することです。

await using AutoLotContext context = factory.CreateDbContext();

// 1 つの作業を行う

Web アプリでは DI によるスコープ管理がよく使われます。

まとめ

EF Core の基本部品は、DbContext、DbSet<T>、エンティティ、変更追跡です。

DbContext は作業単位、DbSet<T> はエンティティ集合への入口、エンティティはデータベース行に対応するクラスです。
変更追跡を理解すると、追加・更新・削除がどのように SQL へ変換されるのか見えやすくなります。

次回は、LINQ クエリがどのように実行されるか、追跡あり/なしの違い、設計時のアプローチを整理します。

C# .NET Entity Framework Core DbContext DbSet ChangeTracker エンティティ
← [C#] Entity Framework Core の役割を理解する [C#] EF Core のクエリ実行と追跡を理解する →

Related Posts

  • [C#] DbContext の設定と保存処理を拡張する Aug 6, 2026
  • [C#] EF Core のエンティティと表示用モデルを設計する Aug 5, 2026
  • [C#] EF Core で更新と削除を扱う Aug 1, 2026
  • [C#] EF Core のコマンドライン操作とマイグレーションを理解する Jul 28, 2026

Table of Contents

  • DbContext は作業単位
  • DbSet はテーブルに対応する入口
  • エンティティとは
  • 変更追跡の考え方
  • ChangeTracker で状態を見る
    • Added
    • Unchanged
    • Modified
    • Deleted
    • Detached
  • 所有される型
  • キーなし型
  • DbContext の寿命に注意する
  • まとめ

Recent Posts

  • [C#] EF Core でデータベースの準備と初期データを扱う Aug 8, 2026
  • [C#] EF Core とリポジトリでデータ操作を整理する Aug 7, 2026
  • [C#] DbContext の設定と保存処理を拡張する Aug 6, 2026
  • [C#] EF Core のエンティティと表示用モデルを設計する Aug 5, 2026
  • [C#] EF Core を中心にデータアクセス層を分ける Aug 4, 2026

Categories

  • C#150
  • .NET149
  • AWS27
  • Laravel16
  • Entity Framework Core15
  • Linux15
  • MySQL9
  • Apache8
  • PHP8
  • Data Access6
  • DynamoDB6
  • セキュリティ6
  • Nginx5
  • WordPress4
  • インフラ4
  • Hugo3
  • .NET Framework1
  • Aurora1
  • Diagnostics1
  • Filament1

Tags

  • C#
  • .NET
  • AWS
  • Laravel
  • コレクション
  • PHP
  • Entity Framework Core
  • セキュリティ
  • MySQL
  • Linux
  • パフォーマンス
  • Apache
  • LINQ
  • System.Collections.Generic
  • デリゲート
  • リフレクション
  • ADO.NET
  • Code Snippet
  • DynamoDB
  • NoSQL
  • PHP-FPM
  • RDS
  • System.Collections
  • Windows
  • メタデータ
  • メモリ管理
  • CIL
  • DoS
  • Nginx
  • SQL Server
  • WordPress
  • ラムダ式
  • 監視
  • 設計
  • Amazon Linux 2023
  • Delegate
  • Docker
  • IDisposable
  • Ipset
  • Iptables
  • LINQ to Objects
  • OPCache
  • Pointer
  • Reflection
  • System.Collections.Specialized
  • Unsafe
  • Webサーバー
  • アセンブリ
  • インターフェース
  • オブジェクト指向
Powered by Hugo & Explore Theme.