Entity Framework Core (EF Core) を使ってPostgreSQLでCRUD操作をする方法について解説します。
※EF Coreを使わずにデータを取得する方法については以下の記事を参照してください。
環境
- Visual Studio 2022
- .NET 8
- PostgreSQL 16.1
事前準備
今回はローカルにインストールしたPostgreSQLに接続するので、まだインストールしていない場合は下記からインストーラをダウンロードしてください。https://www.enterprisedb.com/downloads/postgres-postgresql-downloads
DBやテーブルはマイグレーションによって自動で作成されるので、事前に用意しておく必要はありません。
プロジェクトの作成
Visual Studioで新しいプロジェクトを作成します。今回はコンソールアプリを使って解説します。
Entity Framework Core データベースプロバイダーのインストール
EF CoreでPostgreSQLに接続するために、「Npgsql.EntityFrameworkCore.PostgreSQL」というパッケージをインストールします。
プロジェクト名を右クリックして「NuGetパッケージの管理」をクリックしてください。
「参照」タブで「Npgsql.EntityFrameworkCore.PostgreSQL」と検索し、出てきたパッケージをインストールします。
※パッケージのバージョンはお使いの.NETのバージョン(ターゲットフレームワーク)に合わせるようにしてください(.NET 6ならバージョン6.x系など)
同様の手順で、マイグレーションに必要な「Microsoft.EntityFrameworkCore.Tools」もインストールしてください。
エンティティとコンテキストクラスの用意
Todoを管理する簡単なアプリケーションを作成します。
まずはエンティティクラスと、DBとエンティティクラスの橋渡しを行うコンテキストクラスを作成しましょう。
プロジェクト直下に以下の2つのクラスを作成してください。
まずTodoエンティティを定義します。ID(主キー)、Todo名、完了フラグを保持するテーブルです。
namespace PostgreSQLCurdSample
{
internal class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
}
次にコンテキストクラスを作成します。
「UseNpgsql」の後にPostgreSQLの接続文字列を入力します。
using Microsoft.EntityFrameworkCore;
namespace PostgreSQLCurdSample
{
internal class TodoContext : DbContext
{
public DbSet<Todo> Todos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("Host=localhost;Database=<任意のDB名>;Username=postgres;Password=<設定したパスワード>;");
}
}
Databaseには任意の名前を指定してください。マイグレーション時にここで指定した名前のDBが自動で作成されます。
Usernameはデフォルトのpostgresを指定していますが、必要に応じて変更してください。
マイグレーション
マイグレーションを行うことで、作成したエンティティに合わせてテーブルが作成されます。
「ツール」→「NuGetパッケージマネージャー」→「パッケージマネージャーコンソール」でコンソールを開き、以下のコマンドを実行してみましょう。
Add-Migration InitialCreate
Update-Database
これらのコマンドで行われることは下記の通りです。
- Add-Migrationコマンド:変更内容が記録されたマイグレーションファイルを作成
- Update-Databaseコマンド:マイグレーションファイルの内容をDBに反映
実行後、「Done」と表示されればマイグレーション成功です。
PostgreSQLを確認すると、データベースとテーブルが作成されていることが確認できます。
CRUD操作の実装
それでは、作成されたDBに対してCRUD操作を行うプログラムを実装しましょう。
using Microsoft.EntityFrameworkCore;
using PostgreSQLCurdSample;
using (var context = new TodoContext())
{
// ①登録
context.Todos.Add(new Todo { Name = "プログラミング学習", IsComplete = false });
context.Todos.Add(new Todo { Name = "掃除", IsComplete = false });
context.Todos.Add(new Todo { Name = "買い物", IsComplete = false });
await context.SaveChangesAsync();
// ②1件取得(Idが最も小さいレコード)
var todo = await context.Todos.OrderBy(t => t.Id).FirstAsync();
// ③更新
todo.IsComplete = true;
await context.SaveChangesAsync();
// ④全件取得
var todos = await context.Todos.ToListAsync();
todos.ForEach(t => Console.WriteLine($"④ Id:{t.Id}, Name:{t.Name} IsComplete : {t.IsComplete}"));
// ⑤全件削除
context.RemoveRange(todos);
await context.SaveChangesAsync();
}
Console.ReadLine();
簡単に処理内容を説明します。
- まずTodoアイテムを3つTodosに追加しています。IDは自動採番の設定になっているので指定しなくても問題ありません。SaveChanges(Async)を呼び出すことでINSERT文が実行されます。
- Todosテーブルのデータを昇順にした後に、先頭の1レコードを取得しています。
- ②で取得したデータの完了フラグをtrueに変更後、SaveChangesAsyncを呼び出してUPDATE文を実行しています。
- ToList(Async)を使ってTodosテーブルから全件を取得し、ForEachでコンソールにデータの中身を出力しています。
- RemoveRangeに④で取得したデータを渡すことで全件削除をしています。なお、1件だけ削除したい場合はRemoveメソッドに1つのtodoを渡します。
デバッグ実行すると、コンソール上に④の全件取得結果が表示されます。
上記のコードでは最後に登録したデータを全て削除しているため、DB上ではデータを確認できません。確認したい場合は⑤の削除処理をコメントアウトしてください。
ちなみにEF Core 7.0以降であれば、UpdateとDeleteの処理を以下のように記述できます。
条件に該当する複数のレコードを一括更新/削除する場合に便利です。
// 完了フラグがfalseのレコードを全てtrueに更新
context.Todos.Where(t => !t.IsComplete).ExecuteUpdate(s => s.SetProperty(t => t.IsComplete, true));
// 完了フラグがtrueのレコードを全て削除
await context.Todos.Where(t => t.IsComplete).ExecuteDeleteAsync();