SQLiteは軽量で導入しやすいDBですが、 「あとでSQL ServerやクラウドDBに移行したくなる」ケースも少なくありません。 そこで役立つのがRepositoryパターン(リポジトリパターン)です。
この記事でわかること
・Repositoryパターンの基本アイデア
・SQLite専用コードをアプリ本体から分離する方法
・インターフェース設計と実装例
・将来のDB移行を楽にするポイント
・業務アプリ向けベストプラクティス
・Repositoryパターンの基本アイデア
・SQLite専用コードをアプリ本体から分離する方法
・インターフェース設計と実装例
・将来のDB移行を楽にするポイント
・業務アプリ向けベストプラクティス
1. Repositoryパターンとは?(超ざっくり)
Repositoryパターンは、「DBへのアクセスを1つの窓口にまとめる」設計です。 アプリ本体は「Userを保存して」「User一覧を取ってきて」とだけ依頼し、 SQLiteかSQL Serverかは意識しないようにします。
- UI層:Repositoryのインターフェースだけを見る
- インフラ層:SQLite用の実装を持つ
- 将来:実装だけ差し替えればDB移行が可能
2. ドメインモデル(User)を定義する
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int? Age { get; set; }
}
3. Repositoryインターフェースを定義する
アプリ本体が見るのはこのインターフェースだけ。
public interface IUserRepository
{
User? GetById(int id);
IReadOnlyList<User> GetAll();
void Add(User user);
void Update(User user);
void Delete(int id);
}
4. SQLite実装(Microsoft.Data.Sqlite版)
using Microsoft.Data.Sqlite;
public class SqliteUserRepository : IUserRepository
{
private readonly string _connectionString;
public SqliteUserRepository(string connectionString)
{
_connectionString = connectionString;
}
public User? GetById(int id)
{
using var con = new SqliteConnection(_connectionString);
con.Open();
var sql = "SELECT Id, Name, Age FROM Users WHERE Id = @id";
using var cmd = new SqliteCommand(sql, con);
cmd.Parameters.AddWithValue("@id", id);
using var reader = cmd.ExecuteReader();
if (!reader.Read()) return null;
return new User
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Age = reader.IsDBNull(2) ? (int?)null : reader.GetInt32(2)
};
}
public IReadOnlyList<User> GetAll()
{
var list = new List<User>();
using var con = new SqliteConnection(_connectionString);
con.Open();
var sql = "SELECT Id, Name, Age FROM Users ORDER BY Id";
using var cmd = new SqliteCommand(sql, con);
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
list.Add(new User
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Age = reader.IsDBNull(2) ? (int?)null : reader.GetInt32(2)
});
}
return list;
}
public void Add(User user)
{
using var con = new SqliteConnection(_connectionString);
con.Open();
var sql = "INSERT INTO Users (Name, Age) VALUES (@name, @age)";
using var cmd = new SqliteCommand(sql, con);
cmd.Parameters.AddWithValue("@name", user.Name);
cmd.Parameters.AddWithValue("@age", (object?)user.Age ?? DBNull.Value);
cmd.ExecuteNonQuery();
}
public void Update(User user)
{
using var con = new SqliteConnection(_connectionString);
con.Open();
var sql = "UPDATE Users SET Name = @name, Age = @age WHERE Id = @id";
using var cmd = new SqliteCommand(sql, con);
cmd.Parameters.AddWithValue("@name", user.Name);
cmd.Parameters.AddWithValue("@age", (object?)user.Age ?? DBNull.Value);
cmd.Parameters.AddWithValue("@id", user.Id);
cmd.ExecuteNonQuery();
}
public void Delete(int id)
{
using var con = new SqliteConnection(_connectionString);
con.Open();
var sql = "DELETE FROM Users WHERE Id = @id";
using var cmd = new SqliteCommand(sql, con);
cmd.Parameters.AddWithValue("@id", id);
cmd.ExecuteNonQuery();
}
}
5. UI側からの利用コード(DB種別を意識しない)
public class UserService
{
private readonly IUserRepository _users;
public UserService(IUserRepository users)
{
_users = users;
}
public void CreateSampleUser()
{
_users.Add(new User
{
Name = "Taro",
Age = 25
});
}
public IReadOnlyList<User> GetAllUsers()
{
return _users.GetAll();
}
}
UI層・サービス層は IUserRepository しか見ていないため、
SQLite → SQL Server への移行時も、差し替えるのは実装クラスだけで済みます。
6. 将来のDB移行を楽にするポイント
- SQL方言に依存しすぎない(LIMIT / TOP などは注意)
- Repositoryのメソッド名は「用途ベース」で設計する
(例:
FindActiveUsers()など) - トランザクションはサービス層 or UnitOfWorkでまとめる
- DB固有の型(JSON列など)はドメイン側に漏らさない
7. Dapper / EF Core と組み合わせる場合
Repositoryパターンは、生SQL・Dapper・EF Coreのどれとも相性が良いです。 実装クラスの中だけで好きな技術を使い、インターフェースは共通に保てます。
- 小規模・高速重視 → SQLite + Dapper + Repository
- スキーマ管理重視 → SQLite + EF Core + Repository
8. 業務アプリでのベストプラクティス
- UI層は
IUserRepositoryだけを見る - SQLite固有の処理はインフラ層に閉じ込める
- テスト時はメモリ実装 or モックを差し替える
- 将来のDB移行は「実装クラスの追加」で対応
まとめ:SQLite × Repositoryパターンで“あとから後悔しない”構成に
- SQLiteの軽さを活かしつつ、DB依存を局所化できる
- 将来のDB移行が「実装差し替え」で済む
- テストしやすく、保守性も高い
「とりあえずSQLiteで始めるけど、将来どうなるかわからない」 そんな現場ほど、Repositoryパターンは強力な保険になります。 この記事をベースに、長く運用できるアーキテクチャを組んでみてください。