スキップしてメイン コンテンツに移動

Entity Framework Coreの概念 / メリット / コード例 / 使用方法 / データのインポート、修正、削除 / サンプルコード

 


EF Core?

EF Coreは [Entity Framework]を軽量化したバージョンで、.NET Core 及び.NET 5 以上で使用できる。 データベースとの相互作用を単純化し、開発者がデータベースに対するクエリおよび操作を行うことができるORM(Object-Relational Mapping)ツールである。


主な機能

  • データベースに対するCRUD(Create、Read、Update、Delete)作業を支援する。
  • LINQ(Language Integrated Query)を使ってデータベースクエリを作成することができる。
  • データベーススキーマをコードで定義できるCode Firstアプローチを提供する。
  • 多様なデータベースシステムと互換性がある。

EF Coreのメリット

  • 開発者がデータベースとの相互作用を容易にすることができる。
  • データベースに対する抽象化階層を提供し、メンテナンスと拡張性を向上できる。
  • 多様なデータベースシステムとの互換性を提供する。
  • LINQを使って簡単にデータベースクエリを作成することができる。

EF Coreの限界

  • EF Core は、まだすべてのEntity Framework の機能をサポートしない。
  • 一部の高度なデータベース機能に対するサポートが制限されているケースがある。
  • 性能の側面で、一部の状況では原始SQLクエリを作成する方がより効率的である可能性がある。

EF Coreの使い方

  1. プロジェクトにEF Core NuGet パッケージを追加する。
  2. DbContextクラスを作成し、データベース接続情報を設定する。
  3. モデルクラスを作成し、データベース テーブルとマッピングする。
  4. LINQを使用してデータベースクエリを作成して実行する。
  5. 変更内容をデータベースに保存または更新する。

Entity Framework Coreを使ったデータベースのインストール

  • SQL Serverのインストール
  • dotnet add package Microsoft.EntityFrameworkCore.SqlServer
  • テストのためのInMemoryインストール
  • dotnet add package Microsoft.EntityFrameworkCore.InMemory

DbContext サブクラス作成

public class CatalogContext : DbContext
{
    public CatalogContext(DbContextOptions<CatalogContext> options) : base(options)
    {
    }
    public DbSet<CatalogItem> CatalogItems { get; set; }
    public DbSet<CatalogBrand> CatalogBrands { get; set; }
    public DbSet<CatalogType> CatalogTypes { get; set; }
}

EF Coreの構成 (データベースのリンク情報設定)

  • SQL Serverを使う場合
      builder.Services.AddDbContext<CatalogContext>(
          options => options.UseSqlServer(
              builder.Configuration.GetConnectionString("DefaultConnection")));
  • InMemoryを使う場合
      builder.Services.AddDbContext<CatalogContext>(options =>
          options.UseInMemoryDatabase());

データの取得

var brandItems = await _context.CatalogBrands
    .Where(b => b.Enabled)
    .OrderBy(b => b.Name)
    .Select(b => new SelectListItem {
        Value = b.Id, Text = b.Name })
    .ToListAsync();
  • 名前順整列、Enabled属性でフィルタリング、SelectListItem形式のCatalogBrandsを照会
  • 即時実行するために.ToListAsync()で呼び出しすることが重要である。

データのセーブ

// データの追加 Create
var newBrand = new CatalogBrand() { Brand = "Acme" };
_context.Add(newBrand);
await _context.SaveChangesAsync();

// データの修正 read and update
var existingBrand = _context.CatalogBrands.Find(1);
existingBrand.Brand = "Updated Brand";
await _context.SaveChangesAsync();

// データの削除 read and delete (alternate Find syntax)
var brandToDelete = _context.Find<CatalogBrand>(2);
_context.CatalogBrands.Remove(brandToDelete);
await _context.SaveChangesAsync();
  • EF Coreは、エンティティをインポートして保存するための同期/非同期メソッドをすべてサポートする。
  • ウェブアプリケーションでデータアクセス作業を待っている間、ウェブサーバースレッドが遮断されないようにするために非同期メソッドにasync/awaitパターンを使用することをお勧めする。

関連データの取得

  • EF Coreは、エンティティをインポートする際にデータベースに直接保存されているすべてのプロパティを一緒にインポートする。
  • 関連エンティティリストのようなNavigation属性は null 値で入力される場合がある。
  • このプロセスは、EF Coreがデータを必要以上に持ち込まないようにするため、要求を迅速かつ効率的な方法で処理し、応答を返す必要があるWebアプリケーションでは非常に重要である。
  • 直ちにロード eager loadingを使用してエンティティとの関係を含めるには、次のようにクエリにInclude メソッドを使用して属性を指定することができる。
// .Include を使うためにはusing Microsoft.EntityFrameworkCoreを追加すべき
var brandsWithItems = await _context.CatalogBrands
    .Include(b => b.Items)
    .ToListAsync();

  • 様々な関係を含めることができ、, ThenIncludeを使用して下位関係を含めることもできる。
  • ピリオドで区切られた文字列を.Include() メソッドに伝達してNavigation属性を追加する方法もある。
  • .Include("Items.Products")
  • specificationはフィルタリング論理をカプセル化できるだけでなく、どのプロパティを読み込むかを含め、返却データの形態を指定できる。
// すべての表現式基盤 
Include query = specification.Includes.Aggregate(query, (current, include) 
    => current.Include(include)); 
// 文字列基盤 
Include query = specification.IncludeStrings.Aggregate(query, (current, include) 
    => current.Include(include));
  • また別の方法としては明示的ロードexplict loadingがある。 既読のエンティティに追加データをインポートすることはできるが、DB往復回数を最小限に抑える必要があるウェブアプリケーションでは使用しない方が良い。
  • 基本的に使用しないように設定されており、 Microsoft.EntityFrameworkCore.Proxiesをインストールする必要がある。

コメント

このブログの人気の投稿

CQRSパターンとは?CQRSパターンの説明とメリットまとめ

  CQRS Pattern こちらは勉強のため翻訳したポストです。 元のページは こちら をクリック アプリケーションで 読み取り と 書き込み を分離することを CQRSパターン という。 CQRSパターン は 物理的 、 論理的 に分けることができ、次のような 長所 を持つ。 ・複雑度の管理 ・パフォーマンスの向上 ・拡張性 ・柔軟性 ・保安性 CQRSパターンが何か? Command Query Responsibility Segregation。 直訳すると 命令クエリ責任分離 で、データを読み込みと書き込みをそれぞれのモデルを使用するという意味である。 標準とされてきた方式としては、同一のモデルを用いてデータを読み上げアップデートしていたが、この方式は簡単で、ほとんどのCRUD作業に適している。 しかし、複雑なアプリケーションでは維持管理が難しくなる。 データの書き込みのために複雑なビジネスロジックや有効性検査を行うこともあり データを読み取るためには、さまざまなクエリを実行する必要がある場合がある。 また、どのようにデータモデルを作成するかを考慮する必要がある。 SQL データモデリングのベストプラクティスは正規化されたデータベースが提供されるが、これは一般的には問題ないが、データを書くことに最適化されている。 コマンドとクエリをそれぞれのモデルとして使用すると、個別に拡張することができる。 同じデータベースを使用するとしても論理的に分離できる。 コマンド(命令)およびクエリに対する下位システムをそれぞれのサービスに分割することができる。 また、データの書き込み、読み取りに最適化された複数のデータベースを使用することもできる。 CQSとはどう違うか? CQS (Command Query Separtion) : 命令クエリ分離 基本前提はオブジェクトのメソッドを コマンド と クエリ に分割したこと。 コマンド :システムのステータスを変更するが、値を返さない。 クエリ:値を返すが、システムの状態を変更しない。 (サイドエフェクトなし) コマンドからは値を 返せないという意味ではない 。  一般的な例としては、値を返した後にシステムの状態を変更するスタックから値を引き出してくる場合がある。 CQRSはCQSが進化したもので、CQR...

VueJSのPiniaのまとめ【基礎編】

  目次 Vue 基本構造 Pinia 基本構造 State (Vue) State (Pinia) Getters (Vue) Getters (Pinia) Actions (Vue) Actions (Pinia)     Vue 基本構造 基本構造説明 - Composition API 方式( 別の方式ではOption API方式がある export default{} ) <script setup> // storeを import import { useTodosStore } from '@/stores/todos' // 宣言 const todos = useTodosStore() // --- stateの値をレスポンシブで参照する方法 const { todos, count } = storeToRefs(todos) // --- actionは分割代入して使える const { increment } = todos // --- stateの修正方法3つ // 1. 修正 counter.count++ // 2. $patch 利用 counter.$patch({ count: counter.count + 1 }) // 3. action 이용 counter.increment() </script> <template> <!-- Storeのstateに直接アクセス --> <div>Current Count: {{ counter.count }}</div> </template>   Pinia 基本構造 基本構造説明 Option Store方式 既存と同様state, getters, actionsを直感的に表現する stores/todos-store.js import { defineStore } from 'pinia' export const useTodosStore = defineStore('todos', { //-- storeの名前 state: () =...