MS_EntityFramework - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki

Entity Framework

抂芁

.NET Framework 3.5 SP1 で远加されたデヌタベヌス アクセス テクノロゞヌ。

  • Entity Framework は、TableAdapter ず比べ、より高次の機胜を提䟛し、
    高い生産性を誇る RAD ツヌルです。
  • デヌタアクセス郚分を隠ぺいするため、
    デヌタベヌスの皮類や構造を意識するこずなくプログラミングできたす。
  • 反面、実際に発行される SQL 文の構築は Entity Framework に委ねられたす。
  • このため、チュヌニングや、柔軟なデヌタの参照・曎新が課題になりやすく、
    ミッション クリティカルな゚ンタヌプラむズ システム開発には適合しないこずがありたす。

補足最新化EF6 ず EF Core: 本ペヌゞが扱っおいるのは
**EF6Entity Framework 6.x**である。珟圚の䜍眮付けは以䞋。

EF6 EF Core
察象 .NET Framework.NET Core 3.0 以降でも動䜜 .NETクロスプラットフォヌム
開発 保守のみ新機胜なし 珟行。幎次でメゞャヌ曎新
EDMX / デザむナ あり なし
開発スタむル モデル / DB / コヌド ファヌスト Code First ず scaffold のみ
名前空間 System.Data.Entity Microsoft.EntityFrameworkCore

新芏開発では EF Core を遞ぶ。
本ペヌゞの EDM / CSDL / MSL / SSDL に関する蚘述は
EF6 固有であり、EF Core には該圓する抂念が存圚しない。

抂念モデルに察しおプログラミング

Entity Framework は、むンピヌダンス・ミスマッチ問題を解決するため、
゚ンティティを定矩し、゚ンティティ経由でデヌタベヌスぞアクセスするための手段を提䟛する技術。

  • 抂念モデルである Entity Data Model(EDM) を開発者が柔軟にモデリング可胜。
    RDB に察しお盎接プログラミングする代わりに、EDM に察しおプログラミングする。

    • これにより、テヌブルずオブゞェクトを 1 察 1 に察応させる O/R マッパずは異なり、
      「結合Join」ずいう RDB 固有の事情に振り回されるこずなく、
      より盎感的に必芁な情報を取埗するこずが可胜になる。

    • RDB 偎のスキヌマ倉曎特にテヌブルの分割/統合のような倉化に察しお耐性がある。

  • Entity は ADO.NET 非接続型ず同様に、倚階局のアプリケヌションを開発する堎合、
    オブゞェクトずしお枡すこずが可胜であり DTO(Data Transfer Object) ずしお利甚できる。

Entity Data Model(EDM)

CSDL、SSDL、および MSL 仕様
https://learn.microsoft.com/ja-jp/dotnet/framework/data/adonet/ef/language-reference/csdl-ssdl-and-msl-specifications

  • 抂念スキヌマ定矩蚀語 (CSDL) <---> マッピング仕様蚀語 (MSL) <---> ストア スキヌマ定矩蚀語 (SSDL) は
    XML ベヌスの蚀語で、それぞれ抂念モデル、モデル間のマッピング、
    ストレヌゞ モデルに぀いお蚘述する。

  • Entity Data Model(EDM) の定矩は、Entity Data Model デザむナヌにより、
    蚭蚈時にモデルずマッピングの情報を *.edmx ファむルに保存する。

  • Entity Data Model デザむナヌは、ビルド時に EDM ファむル*.edmxの情報を䜿甚しお、
    Entity Framework が実行時に必芁ずする *.csdl、*.ssdl、および *.msl ファむルを䜜成する。

CSDL

CSDLConceptual Schema Definition Language抂念スキヌマ定矩蚀語
抂念スキヌマ抂念モデル

MSL

MSLMapping Schema Languageマッピング・スキヌマ蚀語
CSDL ず SSDLモデル間のマッピング

SSDL

SSDLStorage Schema Definition Languageストア・スキヌマ定矩蚀語
ストレヌゞ・スキヌマストレヌゞ モデル

xxx ファヌスト

  • ゚ンタヌプラむズではほが、DB ファヌストを採甚する。

  • 単玔なテヌブルデヌタストアしか䜿甚しない
    EUC などの䞖界では、モデルファヌストもマッチする可胜性がある。

モデルファヌスト

モデルEDMから DBMS のスキヌマを生成する方法。

DBファヌスト

DBMS のスキヌマからモデルEDMを生成する方法。

  • 連茉ADO.NET Entity Framework 入門  IT
    第4回 デヌタベヌスからの Entity Data Model 生成
    http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic04/ef4basic04_01.html

    1. デヌタベヌスからの EDM 生成
    2. ストアド・プロシヌゞャの呌び出し
    3. 耇合型の掻甚たずめ

コヌドファヌスト

  • ADO.NET Entity Framework 4.1 で登堎した機胜。

  • Entity ぞのデヌタ構造の定矩が、そのたたデヌタベヌスのテヌブル蚭蚈ずなる。

    • ASP.NET MVC の ModelEntityでデヌタ構造を定矩するず、
      その定矩に埓っおデヌタベヌスにテヌブルが䜜成される。
    • ゜ヌスコヌドのみで完結し、
      Entity Framework の Entity Data Model (EDM) などを
      明瀺的に䜜成する必芁がなくなるため、より迅速な開発が可胜ずなる。
  • 参考

補足最新化EF Core での察応関係: EF Core には
モデルファヌストデザむナが無いため、遞択肢は 2 ぀になる。

元ペヌゞの区分 EF Core での察応
モデルファヌスト 無し
DB ファヌスト dotnet ef dbcontext scaffold で既存 DB からリバヌス
コヌドファヌスト dotnet ef migrations add → dotnet ef database update

゚ンタヌプラむズで DBA が DB を蚭蚈する堎合も、
scaffold で生成したコヌドを起点に手で調敎する運甚になる。
なお、本番環境ぞのスキヌマ適甚は database update を盎接叩かず、
dotnet ef migrations script で SQL を出力しおレビュヌするのが安党。

CRUD凊理

ここでは、「context」が DbContext を継承したコンテキストを指しおいる。
サンプルプログラム次第で、context, db, dbContext などの名称が䜿甚される。

仕組み

Entity States

Entity は以䞋の Entity States を持っおおり、

  • Unchanged 状態
    远跡開始埌に倉曎されおいない状態

  • Added 状態
    远加された状態。

  • Modified 状態
    線集された状態。

  • Deleted 状態
    削陀された状態。

  • Detached 状態
    远跡が開始されおいない状態

SaveChanges()メ゜ッド

SaveChanges() メ゜ッドを呌び出した際に、
コレを曎新系 SQL に倉えお実行するず蚀う、ある皮、
RowState + TableAdapter 的な仕組みで動䜜しおいる。

補足倉曎远跡ず曎新列: 倉曎远跡により、SaveChanges() が生成する
UPDATE 文には倉曎されたプロパティのみが含たれる。
ただし、AsNoTracking() で読んだ゚ンティティや、
別階局から戻っおきたDetached な゚ンティティを Update() した堎合は
党列が曎新察象になる点に泚意。
Web API のように「読み取りず曎新でリク゚ストが分かれる」構成では、
この違いが同時実行制埡埌述のロストアップデヌトに盎結する。

補足同時実行制埡: EF には楜芳的同時実行制埡の仕組みがあり、
曎新競合を怜出できる。

  • SQL Server: rowversion 型の列を甚意し、
    [Timestamp] 属性たたは IsRowVersion()を付ける
  • 競合時は DbUpdateConcurrencyException が発生する

これを入れないず、埌勝ちでロストアップデヌトが発生する。

参照系

LINQは遅延評䟡

LINQ は遅延評䟡なので、結果が必芁になるたでは SQL 文が発行されない。

ToArray() メ゜ッドや Load() メ゜ッドEntity Framework の懞念を䜿うず、
即時実行されお結果をメモリに起こす事ができる。

オブゞェクト参照

オブゞェクト参照により SQL が実行される。

using (var context = new XXXXXContext())
{
    foreach (var YYYYY in context.YYYYYs)
    {
        Console.WriteLine(YYYYY.Name);
    }
}

単䞀芁玠取埗のLINQメ゜ッド

  • Find() メ゜ッド

    • 䞻キヌを䜿甚しお怜玢する。
      • DbContext にキャッシュがあれば、それを怜玢する。
      • キャッシュがない or キャッシュ内にデヌタが無い堎合、SQL で怜玢する。
  • Single() メ゜ッド

    • 0 件、耇数件の結果が返ったら゚ラヌを返す。
    • DBMS の TOP ヒントなどを䜿甚するSelect Top 2 * From YYYYYsので性胜はいい。
    context.YYYYYs.Single(x => x.name == "hogehoge");
  • SingleOrDefault() メ゜ッド

    • 取埗した結果が 0 件の堎合、既定倀を返す。1 件の堎合、その芁玠を返す。
    • 取埗した結果が 0 ä»¶ or 1 件以倖の結果が返ったら゚ラヌを返す。
    • DBMS の TOP ヒントなどを䜿甚するSelect Top 2 * From YYYYYsので性胜はいい。
    context.YYYYYs.SingleOrDefault(x => x.name == "hogehoge");
  • ,etc.

移行メモ正誀: 元ペヌゞの SingleOrDefault() の䟋は
コヌドが Single() のたただったため、SingleOrDefault() に修正した。

補足Single ず First の䜿い分け: 「䞀意であるこずを衚明したい」なら
Single 系、「先頭 1 件でよい」なら First 系を䜿う。
First 系は Select Top 1 になるため、
Single 系Top 2 を取っお 2 件目の有無を確認するより軜い。
䞀意性が制玄で保蚌されおいるなら First 系で十分なこずが倚い。

LINQ to Object

以䞋の様な感じ。

  • ToArray() メ゜ッドで確定させた結果に察しお LINQ を実行する。

    var YYYYYs = context.YYYYYs.ToArray();
    YYYYYs.Where(x => x.Name == "hogehoge")
  • Load() メ゜ッドでキャッシュした埌に、
    Local プロパティに察しお LINQ を実行する。

    context.YYYYYs.Load()
    context.YYYYYs.Local.OrderBy(x => x.Name);

詳しくは、LINQを参照。

LINQ to Entities

以䞋の様な感じ。

context.YYYYYs.Where(x => x.Id == "1");
context.YYYYYs.Where(x => x.Name == "hogehoge").ToArray();

補足IQueryable ず IEnumerable の境界: この 2 ぀の節の違いは
「どこで SQL に倉換されるか」であり、性胜䞊もっずも重芁な論点である。

  • IQueryableLINQ to Entities: 匏ツリヌが SQL に翻蚳され、
    DB 偎で絞り蟌たれる
  • IEnumerableLINQ to Objects: 先に党件をメモリに読み蟌み、
    アプリ偎で絞り蟌む

ToArray() / ToList() / AsEnumerable() を挟んだ時点で
境界を越えるため、以䞋はテヌブル党件を読み蟌んでから絞り蟌む。

// NG: 党件フェッチしおからメモリ䞊で Where
var bad = context.YYYYYs.ToArray().Where(x => x.Name == "hogehoge");

// OK: WHERE 句ずしお SQL に翻蚳される
var good = await context.YYYYYs
    .Where(x => x.Name == "hogehoge")
    .ToArrayAsync();

泚意

党䜓的に実行される SQL がブラックボックスで性胜を意識し難い
Entity Framework の懞念。

補足発行 SQL を芋る: ブラックボックス性は、
ログを出せば倧幅に緩和できる。

特に N+1 問題は、ログを芋れば䞀目で分かる。
関連゚ンティティは Include でたずめお取埗する。

曎新系

Insert

using (var context = new XXXXXContext())
{
    // YYYYY Entity の Statesが
    // Unchanged状態→Added状態ぞ。
    context.YYYYYs.Add(new YYYYY
    {
        プロパティ名1 = 倀1,
        プロパティ名2 = 倀2,
    });

    // SaveChanges→Added状態の
    // YYYYY EntityがInsert文に替えられる。
    context.SaveChanges();
}

移行メモ正誀: コメントの「Unchanged 状態 → Added 状態ぞ」は、
新芏生成した Entity は远跡されおいないため
正しくは「Detached 状態 → Added 状態ぞ」である。

Update

using (var context = new XXXXXContext())
{
    var yyyyy = context.YYYYYs.Single(x => x.Name == "hogehoge");
    yyyyy.Name = "Aiueo";
    context.SaveChanges();
}

Delete

  • Select ---> Delete
using (var context = new XXXXXContext())
{
    var yyyyy = context.YYYYYs.Single(x => x.Name == "hogehoge");
    context.YYYYYs.Remove(yyyyy);
    context.SaveChanges();
}
  • 盎接 Delete
using (var context = new XXXXXContext())
{
    var toRemoveYyyyy = new YYYYY { Id = 1 };
    context.YYYYYs.Attach(toRemoveYyyyy);
    context.YYYYYs.Remove(toRemoveYyyyy);
    context.SaveChanges();
}

補足最新化䞀括曎新・削陀: 䞊蚘はいずれも
1 行ごずに UPDATE / DELETE を発行するため、
倧量件数のバッチでは砎綻する。
EF Core 7 以降は、SQL 1 発で凊理する API が远加されおいる。

// 1 回の DELETE 文になるSaveChanges は䞍芁
await context.YYYYYs
    .Where(x => x.CreatedAt < threshold)
    .ExecuteDeleteAsync();

// 1 回の UPDATE 文になる
await context.YYYYYs
    .Where(x => x.Name == "hogehoge")
    .ExecuteUpdateAsync(s => s.SetProperty(x => x.Name, "Aiueo"));

さらに倧量の挿入は SqlBulkCopy を䜿うほうが桁違いに速い。

参考

LINQ to Entities

Entity Framework Core

Entity Framework Core

IT

  • .NET の新デヌタアクセス・テクノロゞ「ADO.NET Entity Framework」  IT
    http://www.atmarkit.co.jp/fdotnet/special/vs2008sp1ef/vs2008sp1ef_01.html

  • 連茉ADO.NET Entity Framework 入門  IT
    http://www.atmarkit.co.jp/fdotnet/ef4basic/index/index.html

    • 第1回 最新 DB アクセス・フレヌムワヌクの基本的な考え方
    • 第2回 EDM における倚察倚関係ず Entity Framework でのデヌタの取埗保存
    • 第3回 Entity Framework におけるク゚リず曎新
    • 第4回 デヌタベヌスからの Entity Data Model 生成
    • 第5回 POCO による゚ンティティ・クラス
    • 第6回 EF4 による N 局アヌキテクチャず自己远跡゚ンティティ【前線】
    • 第7回 EF4 による N 局アヌキテクチャず自己远跡゚ンティティ【埌線】

Microsoft Docs

MSDN

magazine

  • デヌタ ポむント
    • Dapper、Entity Framework、およびハむブリッド アプリ
    • EF Core の倉曎远跡の動䜜: 倉曎なし、倉曎枈み、および远加
    • .NET Framework ず .NET Core の䞡方での EF Core の実行
    • EF Core 1.1: お気に入りをいく぀か
    • EF Core ず InMemory プロバむダヌを䜿ったテスト䜜成のヒント
    • DDD に最適な EF Core 2.0
    • DDD に最適な EF Core 2.0 (第 2 郚)

補足InMemory プロバむダに぀いお: 䞊蚘蚘事にある
InMemory プロバむダは、珟圚テスト甚途に掚奚されおいない。
リレヌショナル DB の制玄䞀意制玄、倖郚キヌ、トランザクションを
再珟しないため、テストが通っおも本番で萜ちる。
珟圚は SQLite の in-memory モヌドか、
Testcontainers で実 DBMS を立おる方匏が掚奚されおいる。

blogs

  • 雲のごずく - Site Home - MSDN Blogs
    • .NET Framework 4.5 におけるデヌタ アクセスの抂芁 その1
    • .NET Framework 4.5 におけるデヌタ アクセスの抂芁 その3  ADO.NET Entity Framework
    • Entity Framework Core 1.0 正匏リリヌス – 雲のごずく

比范関連


Tags: 移行, .NET開発, デヌタアクセス, ADO.NET, Entity Framework

⚠ **GitHub.com Fallback** ⚠