こんにちは、たびとです。
前回は、ASP.NET Core 6.0 の Entity Framework Core に関して、 Visual Studio 2022 を使って新規プロジェクトで確認しました。
今回は、主要なデータベースに関して、Entity Framework Core による データベースアクセスを試してみようと思います。
- この記事の対象者
- Entity Framework Core によるデータベースアクセス
- SQLite による Entity Framework Core
- PostgreSQL による Entity Framework Core
- MySQL による Entity Framework Core
- まとめ
この記事の対象者
- .NET 6 に興味のある方、これから使う予定のある方
- 各データベースと Entity Framework Core の違いに興味のある方
- PostgreSQL および MySQL を docker で構築してみたい方
Entity Framework Core によるデータベースアクセス
C# による Entity Framework Core の簡単なソースコードを SQLite, PostgreSQL, MySQL, SQL Server, Oracle を使って、 データベース接続以外は同じコードで実行できるのかを試します。
以下の4項目に関して同じコードが適用できるのかを試してみることにします。
- データベース削除(EnsureDeletedAsync)
- データベース作成(EnsureCreatedAsync)
- テーブルへの書き込み(SaveChangesAsync)
- テーブルからの読み込み()
- .NET 6 のコンソールアプリ(.NET Core)
- Main なしのシンプルなコード(最上位レベルステートメントと呼ぶらしい)
- DB接続以外は、できる限り同じコード
データベースは NuGet からパッケージをインストールするだけで使える SQLite を除き、 WSL2/Ubuntu 上の docker で構築することにします。 このとき、Dockerfile や docker-compose.yml を使わずに、 コマンドだけで、できるだけ簡単に構築できるようにします。
WSL2/Ubuntu 上の Docker 構築は、以前の記事も参考にしてください。
SQLite による Entity Framework Core
SQLite による簡単な Entity Framework Core のソースコードを実行します。
SQLite 構築
SQLite は、NuGet パッケージをインストールするだけなので、 インストーラや docker でデータベースを構築する必要はありません。 SQLite は手軽なので、チョッとしたツールを作成するときのデータベースとしては最適だと思います。
SQLite 用のソースコード
NuGet によりインストールしたパッケージは、 Microsoft.EntityFrameworkCore.Sqlite 6.0.0 となります。
using Microsoft.EntityFrameworkCore; await using var context = new SampleContext(); await context.Database.EnsureDeletedAsync(); await context.Database.EnsureCreatedAsync(); context.Samples.Add(new Sample() { Id = 12345, Name = "たびと" }); await context.SaveChangesAsync(); foreach (var item in context.Samples) Console.WriteLine($"{item.Id}: {item.Name}"); public class SampleContext : DbContext { public DbSet<Sample> Samples { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlite("Data Source=sample.db"); } public class Sample { public int Id { get; set; } public string Name { get; set; } }
実行後に生成された SQLite の DDL
ソースコードを実行した後に作成されるテーブル情報(DDL)は、以下の通りです。
CREATE TABLE "Samples" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Samples" PRIMARY KEY AUTOINCREMENT, "Name" TEXT NOT NULL );
ちなみに、sample.db はパスを指定しないと実行ファイルと同じフォルダに出力されます。
PostgreSQL による Entity Framework Core
docker を用いて PostgreSQL を構築し、簡単な Entity Framework Core のソースコードを実行します。
docker による PostgreSQL 構築
docker を用いて、最新の PostgreSQL を起動します。
$ docker run -d --name postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres
上記のデフォルトのデータベースである「postgres」を指定しても、データベースの削除と作成に失敗します。 このため、削除(EnsureDeletedAsync) と 作成(EnsureCreatedAsync) 用に、新規のデータベース「ef」を作り、 このデータベースを対象にします。
PostgreSQL 用のソースコード
SQLite の UseSqlite() を UseNpgsql() に変更し、データベースの接続文字列を記述します。 UseSnakeCaseNamingConvention() は、Npgsql のサイトに掲載されていたもので、 テーブル名・フィールド名をスネークケース形式に置き換えてくれるものです。
PostgreSQL 用 .NET 6 Entity Framework Core のソースコードは以下の通り。
using Microsoft.EntityFrameworkCore; await using var context = new SampleContext(); await context.Database.EnsureDeletedAsync(); await context.Database.EnsureCreatedAsync(); context.Samples.Add(new Sample() { Id = 12345, Name = "たびと" }); await context.SaveChangesAsync(); foreach (var item in context.Samples) Console.WriteLine($"{item.Id}: {item.Name}"); public class SampleContext : DbContext { public DbSet<Sample> Samples { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseNpgsql("host=localhost;port=5432;database=ef;username=postgres;password=postgres") .UseSnakeCaseNamingConvention(); } public class Sample { public int Id { get; set; } public string Name { get; set; } }
ビルドに必要な NuGet パッケージは以下の通り。
- Npgsql.EntityFrameworkCore.PostgreSQL 6.0.1
- EFCore.NamingConventions 6.0.0
実行後に生成された PostgreSQL の DDL
ソースコードを実行した後に作成されるテーブル情報(DDL)は、以下の通りです。 UseSnakeCaseNamingConvention() を削除すると、大文字・小文字が有効になります。
CREATE TABLE public.samples ( id int4 NOT NULL GENERATED BY DEFAULT AS IDENTITY, "name" text NOT NULL, CONSTRAINT pk_samples PRIMARY KEY (id) );
MySQL による Entity Framework Core
docker を用いて MySQL を構築し、簡単な Entity Framework Core のソースコードを実行します。
docker による MySQL 構築
docker から 最新の MySQL を起動します。
$ docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=mysql -p 3306:3306 mysql
DBeaver により MySQL への接続を確認したとき、「SSLを使用する」にチェックを入れて、 「Allow public key retrieval」にチェックを入れないと接続できませんでした。
デフォルトのデータベースである「sys」を指定しても、データベースの削除と作成に失敗します。 このため、削除(EnsureDeletedAsync) と 作成(EnsureCreatedAsync) 用に、新規のデータベース「ef」を作り、 このデータベースを対象にします。
MySQL 用のソースコード
SQLite の UseSqlite() を UseMySql() に変更し、データベースの接続文字列とデータベースの版数を指定します。 LogTo()、EnableSensitiveDataLogging()、EnableDetailedErrors() は、 今回使用した Pomelo.EntityFrameworkCore.MySql のサンプルに記載されたモノを使っています。 これを使うとコンソールに詳細なログが出力されるようになります。
それと、本家のパッケージよりも、Pomelo.EntityFrameworkCore.MySql の方が人気があるようです。
using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; await using var context = new SampleContext(); await context.Database.EnsureDeletedAsync(); await context.Database.EnsureCreatedAsync(); context.Samples.Add(new Sample() { Id = 12345, Name = "たびと" }); await context.SaveChangesAsync(); foreach (var item in context.Samples) Console.WriteLine($"{item.Id}: {item.Name}"); public class SampleContext : DbContext { public DbSet<Sample> Samples { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql("server=localhost;user=root;password=mysql;Database=ef", new MySqlServerVersion(new Version(8, 0, 27))) .LogTo(Console.WriteLine, LogLevel.Information) .EnableSensitiveDataLogging() .EnableDetailedErrors(); } public class Sample { public int Id { get; set; } public string Name { get; set; } }
実行後に生成された MySQL の DDL
ソースコードを実行した後に作成されるテーブル情報(DDL)は、以下の通りです。
CREATE TABLE `Samples` ( `Id` int NOT NULL AUTO_INCREMENT, `Name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB AUTO_INCREMENT=12346 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
まとめ
前編では、SQLite・PostgreSQL・MySQL を使って、.NET 6 で Entity Framework Core を 作成した場合、どれぐらい違いがでるのかを確認しましたが、 DbContext の UseXxx メソッドの変更だけで、簡単に変更できることがわかりました。
後編では、今回と同様のソースコードを用いて、 SQL Server と Oracle を試していきます。
今後は、Entity Framework Core へのシフトが加速すると、 データベースの移行が簡単になるのかもしれません。
最後に参考サイトを掲載しておきます。
では、皆さん、よい旅を。