DbContextとDbSetの基礎
DbContextを設定し、エンティティを定義し、接続文字列を構成して、最初のクエリを実行します。
「DbContextとDbSetの基礎」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
Entity Framework Coreとは
EF Coreは、.NET公式のオブジェクトリレーショナルマッパー(ORM)です。C#クラス(エンティティ)をデータベースのテーブルにマッピングし、ほとんどの操作でSQLを直接書かずにLINQを使ってデータを検索・保存できます。
エンティティの定義
エンティティとは、プロパティがデータベースの列にマッピングされる単純なC#クラスです。慣例により、Idまたは<TypeName>Idという名前のプロパティが主キーになります。
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "";
public decimal Price { get; set; }
public int Stock { get; set; }
public DateTime CreatedAt { get; set; }
}DbContextの作成
DbContextはデータベースへの入り口です。エンティティごとにDbSet<T>プロパティを保持し、接続、変更追跡、トランザクションを管理します。
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
public DbSet<Product> Products => Set<Product>();
public DbSet<Order> Orders => Set<Order>();
}DI への DbContext の登録
Program.cs で AddDbContext を呼び出し、コンテキストを Scoped サービスとして登録するとともに、データベースプロバイダーを構成します。
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("Default")));
// For SQLite (great for development/testing):
// options.UseSqlite("Data Source=app.db");DbSet を使った基本的なクエリ
DbSet<T> は LINQ 演算子を公開します。クエリは列挙されるまで(await ...ToListAsync() が実行されるまで)実行されません。これを遅延実行と呼びます。
public class ProductService
{
private readonly AppDbContext _db;
public ProductService(AppDbContext db) => _db = db;
public async Task<List<Product>> GetExpensiveAsync(decimal minPrice)
{
return await _db.Products
.Where(p => p.Price >= minPrice)
.OrderBy(p => p.Name)
.ToListAsync();
}
}主キーによる検索
FindAsync はデータベースにアクセスする前に、ローカルの変更追跡キャッシュを確認します。主キーで検索する場合に使用すると、不要な往復通信を避けられます。
var product = await _db.Products.FindAsync(42);
if (product is null)
throw new KeyNotFoundException("Product not found");
// For complex keys, pass all key values:
var orderLine = await _db.OrderLines.FindAsync(orderId, productId);新しいレコードの追加
Add を呼び出してエンティティを挿入対象としてキューに追加し、その後 SaveChangesAsync を呼び出して変更を確定します。EF Core が INSERT SQL を生成し、自動生成された Id を設定します。
var product = new Product
{
Name = "Mechanical Keyboard",
Price = 149.99m,
Stock = 50,
CreatedAt = DateTime.UtcNow
};
_db.Products.Add(product);
await _db.SaveChangesAsync();
Console.WriteLine(product.Id); // Auto-generated PKレコードの更新
EF Core によって読み込まれたエンティティは追跡されます。プロパティを直接変更して SaveChangesAsync を呼び出すと、EF Core が変更を検出し、最適化された UPDATE 文を生成します。
var product = await _db.Products.FindAsync(42);
if (product is not null)
{
product.Price = 129.99m;
product.Stock -= 1;
await _db.SaveChangesAsync(); // UPDATE Products SET Price=...
}レコードの削除
Remove を呼び出してエンティティを削除対象としてマークし、その後 SaveChangesAsync を呼び出します。エンティティを読み込まずに一括削除する場合は、.NET 7 以降の ExecuteDeleteAsync を使用します。
// Delete a tracked entity
_db.Products.Remove(product);
await _db.SaveChangesAsync();
// Bulk delete without loading (EF Core 7+)
await _db.Products
.Where(p => p.Stock == 0)
.ExecuteDeleteAsync();Fluent API による構成
OnModelCreating をオーバーライドし、Fluent API を使用してエンティティを構成します。テーブル名、列の型、制約、インデックス、リレーションシップなどを設定できます。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>(entity =>
{
entity.ToTable("products");
entity.Property(p => p.Name).IsRequired().HasMaxLength(200);
entity.Property(p => p.Price).HasColumnType("decimal(18,2)");
entity.HasIndex(p => p.Name);
});
}実践例: DbContext を使ったリポジトリ
一般的なリポジトリでは DbContext をラップし、データアクセスのロジックを集約するとともに、クエリの詳細がサービスクラスに漏れないようにします。
public class ProductRepository : IProductRepository
{
private readonly AppDbContext _db;
public ProductRepository(AppDbContext db) => _db = db;
public async Task<Product?> GetByIdAsync(int id)
=> await _db.Products.AsNoTracking().FirstOrDefaultAsync(p => p.Id == id);
public async Task<List<Product>> SearchAsync(string query)
=> await _db.Products
.Where(p => p.Name.Contains(query))
.AsNoTracking()
.ToListAsync();
}理解度チェック
EF Core でクエリを実行するとき、AsNoTracking() は何をしますか?
まとめ: DbContext と DbSet の基本
重要なポイント:
- DbContext はデータベースとのセッションであり、DbSet<T> はテーブルを表します
- DI では
AddDbContextを使って登録します。デフォルトでは Scoped です - LINQ クエリは遅延実行されます。
ToListAsyncやFirstOrDefaultAsyncで実行します - 変更追跡により、SaveChangesAsync を使って UPDATE や DELETE を自動的に実行できます
- 読み取り専用のクエリには
AsNoTracking()を使用すると、パフォーマンスを向上できます
よくある質問
「DbContextとDbSetの基礎」レッスンは無料ですか?
はい。「DbContextとDbSetの基礎」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「DbContextとDbSetの基礎」で何を学びますか?
DbContextを設定し、エンティティを定義し、接続文字列を構成して、最初のクエリを実行します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「DbContextとDbSetの基礎」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- DbContextとDbSetの基礎
- Migrationとスキーマ管理
- EF CoreによるCRUD操作
- リレーションシップ:一対多と多対多