1.Entity Framework Core (EF Core) について

EF Core は、.NET向けのO/Rマッパー (ORM) ライブラリです。 DBのテーブルやビューなどのデータを、.NETクラスとして扱うことができるため データベース操作をC#などのオブジェクト指向プログラミングで実装できます。

EF Coreは複数のデータベースプロバイダをサポートしているため 一貫したAPIを使用して様々なデータベースシステムにアクセスできます。

データベース内の各テーブルはエンティティとしてマップします。 DbContextクラスはエンティティを操作したり、LINQクエリを実行したり、 データベースの変更を追跡したりするために利用されるクラスで、 データベースとのインタラクションを管理する重要なクラスです。

マップクラス
// マップクラス
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

DbContextの定義
// DbContextの定義
using System.Data.Entity;

public class MyDbContext : DbContext
{
    public MyDbContext() : base("name=MyConnectionString")
    {
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Product> Products { get; set; }
    // 他のテーブルを追加
}

Entity Framework CoreではSQLクエリを介さずにLINQクエリを介してデータベースへクエリを実行するため データの操作がシンプルかつ直感的になります。

CRUD操作
// データの操作
using System.Data.Entity;

using (var context = new MyDbContext())
{
    // データの取得
    var users = context.Users.ToList();

    // データの追加
    var user = new User { Name = "Taro" };
    context.Users.Add(user);
    context.SaveChanges();

    // データの更新
    var existingUser = context.Users.Find(1);
    if (existingUser != null)
    {
        existingUser.Name = "Hanako";
        context.SaveChanges();
    }

    // データの削除
    var userToDelete = context.Users.Find(1);
    if (userToDelete != null)
    {
        context.Users.Remove(userToDelete);
        context.SaveChanges();
    }
}

その他のLINQ機能
・フィルタリング: Where
・ソート: OrderBy, OrderByDescending
・選択: Select
・グループ化: GroupBy
・結合: Join
・集計: Count, Sum, Average

メソッド構文では、メソッドチェーンを使用してクエリを作成します。

メソッドチェーン
// メソッドチェーン

using (var context = new MyDbContext())
{
    // ユーザーの取得
    var users = context.Users
                       .Where(u => u.Name.StartsWith("A"))
                       .OrderBy(u => u.Name)
                       .ToList();
}

クエリ構文ではSQLに似た構文でクエリを記述できます。

クエリ
// クエリ構文

using (var context = new MyDbContext())
{
    var users = (from u in context.Users
                 where u.Name.StartsWith("A")
                 orderby u.Name
                 select u).ToList();
}

2.EF Coreの導入 database first

Entity Framework Coreを使用してモデルを生成する方法について説明します。 database firstとcode firstでのアプローチがあります。

今回はDatabase Firstアプローチでモデルを生成する方法について説明します。 既存のDatabaseからモデルを生成するため先にDatabaseが必要となるアプローチです。

dotnetプロジェクト作成
dotnet new webapp -n EFSampleProject


cd EFSampleProject

テンプレート "ASP.NET Core Web アプリ"を作成します。 次にSqlServerを利用するためNuGetパッケージのインストールを行います。

NuGetパッケージのインストール
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

dotnet add package Microsoft.EntityFrameworkCore.Tools

Database Firstでは、既存データベースからモデルを生成するためScaffold-DbContextコマンドを使用します。

dotnet-efを使用したい場合はローカルにインストールする方法とグローバルにインストールする必要があります。

ローカルにインストールする場合はローカルツールを管理するためのマニフェストを作成します。 --local オプションはプロジェクトのルートディレクトリにいる場合、ローカルマニフェストが既に作成されていると省略できます。

ローカルインストール
dotnet new tool-manifest
dotnet tool install dotnet-ef

グローバルインストール
dotnet tool install --global dotnet-ef

インストールの確認
dotnet tool list

パッケージ ID       バージョン       コマンド           マニフェスト

------------------------------------------------------------------------------------------------------
dotnet-ef      5.0.5      dotnet-ef     *****\EFSampleProject\.config\dotnet-tools.json

アンインストールをしたい場合は以下のコマンドでアンインストールします。

アンインストール方法
# グローバルの場合
dotnet tool uninstall --global dotnet-ef

# ローカルの場合
dotnet tool uninstall dotnet-ef --local

以下のようにSqlServerとDatabase名とユーザ、パスワードを指定します Window認証で接続する場合はユーザ、パスワードは不要で「Integrated Security=True;」を接続文字列に追加します。

dotnet ef dbcontext scaffold "Server=your_server;Database=your_database;User Id=your_user;Password=your_password;" Microsoft.EntityFrameworkCore.SqlServer

以下のようなエラーが発生する場合

A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - 信頼されていない機関によって証明書チェーンが発行されました。)

SQL Server に接続する際に SSL 接続が要求されているが、使用している証明書が信頼されていないために発生しています。 この場合は接続文字列に TrustServerCertificate=true を追加することで、証明書の検証をスキップすることができますが これはセキュリティ上のリスクがあるため、開発環境やテスト環境での使用に留めてください。

実行が完了するとフォルダ内にDbContextとエンティティクラスが生成されます。 scaffold コマンドには、さまざまなオプションがあります。

sys.objectsから継承されたカタログ ビューなどで以下が存在する

オプション内容
--output-dir (DIR)生成される DbContext とエンティティクラスの出力先ディレクトリを指定
--context-dir (DIR)DbContext を特定のディレクトリに生成する
--context (NAME)生成する DbContext クラスの名前を指定
--schema (SCHEMA)特定のスキーマに属するテーブルのみをスキャフォールディングする
--table (TABLE)特定のテーブルのみをスキャフォールディングする場合に使用。複数のテーブルを指定することも可能
--no-onconfiguringOnConfiguring メソッドを生成しないように指定しDbContext に接続文字列を含めないように指定
--force既存のファイルを上書きを指定
--data-annotationsデータアノテーションを使用して、モデルの構成を生成

以下はSampleのDBでのDbContextクラスの生成内容です。

DbContext
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace EFSampleProject;

public partial class SampleContext : DbContext
{
    public SampleContext()
    {
    }

    public SampleContext(DbContextOptions<SampleContext> options)
        : base(options)
    {
    }

    public virtual DbSet<SampleEntity> SampleEntities { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
        => optionsBuilder.UseSqlServer("Server=*********;Database=Sample;Integrated Security=True;TrustServerCertificate=true;");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<SampleEntity>(entity =>
        {
            entity.ToTable("SampleEntity");

            entity.Property(e => e.Id).ValueGeneratedNever();
            entity.Property(e => e.Amount).HasColumnType("decimal(30, 8)");
            entity.Property(e => e.Name).HasMaxLength(200);
        });

        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}


Entity
using System;
using System.Collections.Generic;

namespace EFSampleProject;

public partial class SampleEntity
{
    public long Id { get; set; }

    public string Name { get; set; }

    public decimal? Amount { get; set; }
}


DBへアクセスするための文字列がOnConfiguringメソッドに埋め込まれていますが DbContextの接続文字列をappsettings.jsonから読み取るようにしてOnConfiguringメソッドをオーバーライドせずに依存性注入を使用するのが一般的です。 Startup.csまたはProgram.csにDbContextを登録して利用します。

public IConfiguration Configuration { get; }

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<SampleContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}

appsettings.json は、ASP.NET Core アプリケーションの設定を管理するためのファイルです。 このファイルには、アプリケーションの構成設定や接続文字列、ログの設定などを JSON 形式で記述します。

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=your_server;Database=your_database;User Id=your_user;Password=your_password;"
  }
}

DbContext
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace EFSampleProject;

public partial class SampleContext : DbContext
{
    private readonly string _connectionString;

    public SampleContext(DbContextOptions<SampleContext> options, IConfiguration configuration)
        : base(options)
    {
        _connectionString = configuration.GetConnectionString("DefaultConnection");
    }

    public virtual DbSet<SampleEntity> SampleEntities { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<SampleEntity>(entity =>
        {
            entity.ToTable("SampleEntity");

            entity.Property(e => e.Id).ValueGeneratedNever();
            entity.Property(e => e.Amount).HasColumnType("decimal(30, 8)");
            entity.Property(e => e.Name).HasMaxLength(200);
        });

        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

生成されたDbContextを使用してデータのCRUD操作を行います。

    using (var context = new SampleContext(options))
    {
        var entities = context.SampleEntity.ToList();
        // データの操作
    }
注意点:dotnet-ef、NuGet パッケージのバージョンなどに注意して利用してください

本コンテンツはプロモーションが含まれます。