本文へスキップ
BecomeCoder

C#デザインパターンコース · 第3章 現代の設計パターン · レッスン20

Repository パターン

ブラウザで完結

導入

「DBからユーザーを探す」処理が業務ロジックの中に直書きされていると、SQLとビジネスルールが混ざって読みにくくなります。Repository パターンは、データの出し入れを「コレクションのような窓口」に隠し、業務ロジックを保存先から切り離します。

図解

flowchart LR
    S["業務ロジック"] -->|Add / FindById| R["IRepository<User>"]
    R -.-> DB["DB / メモリ / ファイル<br/>(差し替え可能)"]
    style R fill:#e1f5fe

サンプル

IUserRepository repo = new InMemoryUserRepository();
repo.Add(new User(1, "Taro"));
repo.Add(new User(2, "Jiro"));

var u = repo.FindById(1);
Console.WriteLine(u?.Name);   // Taro

record User(int Id, string Name);

interface IUserRepository
{
    void Add(User user);
    User? FindById(int id);
}
class InMemoryUserRepository : IUserRepository
{
    private readonly List<User> _users = new();
    public void Add(User user) => _users.Add(user);
    public User? FindById(int id) => _users.FirstOrDefault(u => u.Id == id);
}
  • Repository は「データの出し入れ」を抽象化した窓口
  • 業務ロジックは IUserRepository にだけ依存し、保存先(DB/メモリ)を知らない
  • テストではメモリ実装、本番ではDB実装、と差し替えられる

やってみよう

FindById に加えて All() で全件を返すメソッドを増やし、名前順に並べて出力してみましょう。呼び出し側はSQLを一切書きません。

演習

interface IBookRepository { void Add(string title); int Count(); }

// TODO: リストに溜めて Count() で件数を返す InMemoryBookRepository を実装してください
___

var repo = new InMemoryBookRepository();
repo.Add("C#入門");
repo.Add("設計の基本");
Console.WriteLine(repo.Count());   // 2
  • 期待される出力: 2
ヒント1を見る

class InMemoryBookRepository : IBookRepository { private readonly List<string> _b = new(); public void Add(string t) => _b.Add(t); public int Count() => _b.Count; }

ヒント2を見る

内部で List<string> に溜め、Count はそのリストの件数を返します

まとめ

  • Repository はデータアクセスを「コレクション風の窓口」に隠す
  • 業務ロジックを保存先から切り離せる
  • メモリ実装とDB実装を差し替えでき、テストが容易

次回: 複数の変更をまとめて確定する Unit of Work です。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。