[[Open棟梁Project>http://opentouryo.osscons.jp/]] - [[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]

-[[戻る>データアクセスのいろいろ]]

* 目次 [#s84ee5e9]
#contents

*概要 [#e1c8710d]
.NET Framework 3.5 SP1で追加されたデータベースアクセステクノロジー

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

**概念モデルに対してプログラミング [#g3c9b5e5]
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) [#se4e2907]
CSDL、SSDL、および MSL 仕様~
http://msdn.microsoft.com/ja-jp/library/vstudio/bb399604.aspx

-概念スキーマ定義言語 (CSDL) <---> マッピング仕様言語 (MSL) <---> ストア スキーマ定義言語 (SSDL) は ~
XML ベースの言語で、それぞれ概念モデル、モデル間のマッピング、ストレージ モデルについて記述する。

-Entity Data Model(EDM) の定義は、Entity Data Model デザイナーにより、~
設計時にモデルとマッピングの情報を *.edmx ファイルに保存する。

-Entity Data Model デザイナーは、ビルド時に EDMファイル(*.edmx)の情報を使用して、~
Entity Framework が実行時に必要とする *.csdl、*.ssdl、および *.mslファイルを作成する。

***CSDL [#u45bdd9b]
CSDL(Conceptual Schema Definition Language:概念スキーマ定義言語)~
概念スキーマ(概念モデル)

-CSDL 仕様~
http://msdn.microsoft.com/ja-jp/library/vstudio/bb399292.aspx

***MSL [#eb804616]
MSL(Mapping Schema Language:マッピング・スキーマ言語)~
CSDLとSSDL(モデル間)のマッピング

-MSL 仕様~
http://msdn.microsoft.com/ja-jp/library/vstudio/bb399202.aspx

***SSDL [#r9199843]
SSDL(Storage Schema Definition Language:ストア・スキーマ定義言語)~
ストレージ・スキーマ(ストレージ モデル)

-SSDL 仕様~
http://msdn.microsoft.com/ja-jp/library/vstudio/bb399559.aspx

** xxx ファースト [#m1aabfea]

-エンタープライズではほぼ、DBファーストを採用する。

-単純なテーブル(データストア)しか使用しない~
EUCなどの世界では、モデルファーストもマッチする可能性がある。

***モデルファースト [#e8fd5f15]
モデル(EDM)からDBMSのスキーマを生成する方法

-連載:ADO.NET Entity Framework入門 - @IT
--第2回 EDMにおける多対多関係とEntity Frameworkでのデータの取得/保存~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic02/ef4basic02_01.html
>
+多対多関係の実現
+EDMからデータベースの自動生成~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic02/ef4basic02_02.html
+Entity Frameworkで自動生成されるクラス
+Entity Frameworkでのデータ保存/取得サンプル

***DBファースト [#k0847c21]
DBMSのスキーマからモデル(EDM)を生成する方法

-連載:ADO.NET Entity Framework入門 - @IT~
第4回 データベースからのEntity Data Model生成~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic04/ef4basic04_01.html
>
+データベースからのEDM生成
+ストアド・プロシージャの呼び出し
+複合型の活用/まとめ

***コードファースト [#rcec17e4]
-ADO.NET Entity Framework 4.1 で登場した機能。

-Entityへのデータ構造の定義が、そのままデータベースのテーブル設計となる。
--ASP.NET MVC のModel(Entity)でデータ構造を定義すると、~
その定義に従ってデータベースにテーブルが作成される。
--ソースコードのみで完結し、~
Entity Framework のEntity Data Model (EDM) などを~
明示的に作成する必要がなくなるため、より迅速な開発が可能となる。

-参考
--Entity Framework Code First | densan-labs.net~
http://densan-labs.net/tech/codefirst/index.html

--既存のデータベースでEF『コード・ファースト』を使用 (1/4):CodeZine(コードジン)~
https://codezine.jp/article/detail/5400

--第5回 POCOによるエンティティ・クラス - @IT~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic05/ef4basic05_03.html
---Entity Framework 4でコード・ファースト開発 - @IT~
http://www.atmarkit.co.jp/fdotnet/scottgublog/20100726codefirst/codefirst.html

*CRUD処理 [#t3428a33]
-4. データの挿入、読み出し、更新、削除 | densan-labs.net~
http://densan-labs.net/tech/codefirst/adddelete.html

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

**仕組み [#rea26718]
***Entity States [#zd380b94]
Entityは以下のEntity Statesを持っており、

-Unchanged状態~
追跡開始後に変更されていない状態

-Added状態~
追加された状態。

-Modified状態~
編集された状態。

-Deleted状態~
削除された状態。

-Detached状態~
追跡が開始されていない状態

***SaveChanges()メソッド [#u73b2b58]
SaveChanges()メソッドを呼び出した際に、~
コレを更新系SQLに変えて実行すると言う、ある種、~
RowState + TableAdapter的な仕組みで動作している。

**参照系 [#tc33cb30]

***LINQは遅延評価 [#eb4398f5]
LINQは遅延評価なので、結果が必要になるまではSql文が発行されない。

[[ToArray()メソッド>#d887a52f]]や、[[Load()メソッド>#ac9d6a53]]を使うと、~
即時実行されて結果をメモリに起こす事ができる。

***オブジェクト参照 [#s28b7a9f]
オブジェクト参照によりSQLが実行される。

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

***単一要素取得のLINQメソッド [#y0fe17de]

-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.Single(x => x.name == "hogehoge");

-,etc.

-参考
--FirstOrDefaultとかLastなど単一要素取得のLINQメソッド - Qiita~
http://qiita.com/RyotaMurohoshi/items/0d4cf421e0eb4a9b4765
---ElementAt
---ElementAtOrDefault
---First
---FirstOrDefault
---Single
---SingleOrDefault

***[[LINQ to Object>LINQ#b29ceb6f]] [#t2396e97]
以下の様な感じ。

-[[ToArray()メソッド>#d887a52f]]で確定させた結果に対してLINQを実行する。
 var YYYYYs = context.YYYYYs.ToArray();
 YYYYYs.Where(x => x.Name == "hogehoge")

-[[Load()メソッド>#ac9d6a53]]でキャッシュした後に、~
Localプロパティに対してLINQを実行する。
 context.YYYYYs.Load()
 context.YYYYYs.Local.OrderBy(x => x.Name);

詳しくは、[[LINQ to Object>LINQ#b29ceb6f]]を参照。

***[[LINQ to Entities>#b48c3a6f]] [#me91998f]
以下の様な感じ。

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

詳しくは、[[次章>#b48c3a6f]]を参照。

***注意 [#f6252c64]
[[全体的に実行されるSQLがブラックボックスで性能を意識し難い。>#iec49e1b]]

**更新系 [#x69c42b1]

***Insert [#n5790853]
 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();
 }

***Update [#k94f6862]
 using (var context = new XXXXXContext())
 {
     var yyyyy = context.YYYYYs.Single(x => x.Name == "hogehoge");
     yyyyy.Name = "Aiueo";
     context.SaveChanges();
 }

***Delete [#te140de3]
-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();
 }

*LINQ to Entities [#b48c3a6f]
-[[LINQ]]との関連もチェックして下さい。

-書籍転載:ASP.NET MVC 5 実践プログラミング - LINQとは?[C#] - Build Insider~
http://www.buildinsider.net/web/bookaspmvc5/050301

-連載:ADO.NET Entity Framework入門 - @IT~
第3回 Entity Frameworkにおけるクエリと更新~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic03/ef4basic03_02.html

-LINQ to Entities~
http://msdn.microsoft.com/ja-jp/library/vstudio/bb386964.aspx

>LINQ to Entities, QueryBuilder, Entity SQL

--Entity SQL~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic03/ef4basic03_01.html の前半
--QueryBuilder~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic03/ef4basic03_01.html の後半
--LINQ to Entities~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic03/ef4basic03_02.html

*外部スキーマ云々的なトピック [#l921da5a]

**JOINのサポート [#xe24f2b1]

***JOINの使用 [#k6b2044c]
-EntityFramework(CodeFirst)でJoinを試してみる : 日曜ゲームクリエータの日記~
http://kazenetu.exblog.jp/19246594/
-[Entity Framework] LINQ で JOIN 句を使用して複数テーブルからデータを取得する: ある SE のつぶやき~
http://fnya.cocolog-nifty.com/blog/2014/01/entity-framew-6.html
-[Entity Framework] LINQ で LEFT JOIN 句を使用して複数テーブルからデータを取得する: ある SE のつぶやき~
http://fnya.cocolog-nifty.com/blog/2014/01/entity-framew-7.html

***JOINを使用しない内部結合 [#u99ee7fa]
-Entity FrameworkでJoinを使わずに内部結合する - Qiita~
http://qiita.com/keidrumfreak/items/f15d36bfdb35ca2dc6b0
-[Entity Framework] LINQ で JOIN 等を使わずに複数テーブルからデータを取得する: ある SE のつぶやき~
http://fnya.cocolog-nifty.com/blog/2014/01/entity-framew-5.html

**集計処理のサポート [#aec2292d]

*性能問題 [#iec49e1b]
全体的に、

-contextへのアクセス
-呼び出すLINQメソッド

から

-どういうSQLが実行されるのか?
-内部動作はどのようになっているのか?

などがブラックボックス化されているため、~
Entity Framework自体の仕様に精通していないと、

ハイパフォーマンスな実装をすることができない。

という問題がある。

**検索SQLが検索キーや射影の列名を指定しない [#e168576f]
[[foreach>#s28b7a9f]]でデータアクセスした場合など、~
検索SQLが検索キーや射影の列名を指定しないので性能的に問題になる。

**Iterator的にDBアクセスしてしまう。 [#k7f89864]
以下の様な手段により、処理対象のEntityをメモリに起こしてしまう。

***ToArray()メソッド [#d887a52f]
この場合、ToArray()メソッドを使って、はじめに結果を確定させる。

 var YYYYYs = context.YYYYYs.ToArray();

***Load()メソッド [#ac9d6a53]
この場合、Load()メソッドを使って、DbContext内にデータをキャッシュさせる。

 context.YYYYYs.Load();

この後、context.YYYYYsにアクセスしてもSQLは実行されない。

**[[LINQ to Object>#t2396e97]] vs [[LINQ to Entities>#b48c3a6f]] [#xdb6f7c2]
***処理される場所が異なる [#ca233ef8]
-[[LINQ to Object>#t2396e97]]は、メモリ上での処理
-[[LINQ to Entities>#b48c3a6f]]は、DBMS上での処理

となる。

-基本的には、[[LINQ to Object>#t2396e97]]が高速だが、

-ストレージが必要な大量データ処理になってくると、~
[[LINQ to Entities>#b48c3a6f]]の方が高速になる可能性がある。

***処理結果が異なる [#k3acdfa7]
処理される場所だけでなく、処理結果が異なることがある。

-以下は、DB側でNameでソート(OrberBy)される。
 context.YYYYYs.OrberBy(x => x.Name).ToArray()

-以下はDBからロードされた後、メモリ上でNameでソート(OrberBy)される。
 context.YYYYYs.ToArray().OrderBy(x => x.Name)

[[DBMSの照合順序>SQL Server の照合順序]]などの関係により、~
処理される場所によって、ソート(OrberBy)順が異なるためである。

**トラッキングしない [#l2b0353c]
AsNoTracking()メソッドでCollectionを取得すると、~
[[Entity States>#zd380b94]]のトラッキングをしなくなる。

 var YYYYYs = context.YYYYYs.AsNoTracking().ToArray();

これにより、使用するメモリ量を削減できる。

*コードファースト [#e2f2f6d2]
-クラス名(+s)がテーブル名にマップされる。
-プロパティ名がカラム名にマップされる。
-主キーはid or クラス名 + id がデフォルト。

-参考
--Entity Framework Code First | densan-labs.net~
http://densan-labs.net/tech/codefirst/index.html

**マイグレーション [#heee7759]
コードファーストのデータモデルクラスの変更をもとに、~
既存のデータを残したままデータベースのテーブルを変更する機能。

-Entity Framework Code First Migrations~
http://msdn.microsoft.com/ja-jp/data/jj591621.aspx

-3. データベースマイグレーション | densan-labs.net~
http://densan-labs.net/tech/codefirst/migration.html

**規約 [#ed82e278]
コードファーストでは規約に基づいてEntityとDatabaseを紐付ける。

***属性 [#p7736f99]
属性による規約

|項番|属性名|説明|h
|1|Table|EntityとTable間のマッピング|
|2|Column|EntityのPropertyとTableのColumn間のマッピング|
|3|ComplexType|Entityの複数のProperty(Properties)とTable間のマッピング&br;&color(red){ComplexTypeの複数のProperty(Properties)は、別のTableに切り出される。};|
|4|Key|EntityのPropertyを対応するTableのPrimaryKeyに設定する。|
|5|Required|EntityのPropertyに対応するTableのColumnをNOT NULLに設定する。&br;&color(red){MVCのModelMetadataとして検証処理に使用される。};|
|6|MaxLength|EntityのPropertyに対応するTableのColumnのデータ長を設定する。&br;&color(red){MVCのModelMetadataとして検証処理に使用される。};|
|7|Index|EntityのPropertyに対応するTableのColumnを使用した非クラスタ化・インデックスを作成する。|
|8|NoMapped|EntityのPropertyをDatabaseにマップしない。|

その他、DbContextを継承したContextのコンストラクタで接続文字列を決定できる。

***Fluent API [#z5aeeab8]
Fluent APIによる規約

-Fluent APIとDbContextの機能 - @IT~
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4codefirst03/ef4codefirst03_01.html

-Entity Framework Fluent API - プロパティと型の構成/マッピング~
https://msdn.microsoft.com/ja-jp/data/jj591617.aspx

***ナビゲーション・プロパティ [#gc07c222]
エンティティ間の関連(アソシエーション)を表す。
-x対一は、オブジェクト参照を使用。
-x対多は、ICollection<T>を使用。


*批判 [#j3882416]
-性能と柔軟性が重視されるエンタープライズの領域では、使い難いとの批判も多い模様。
-ツール等のスタンドアロンのプログラム、情報系システムなどのEUCによるRAD開発などにはマッチする可能性もある。

-また、ADO.NETは枯れた技術であるのに対し、Entity Frameworkは進化の余地がある。

--Entity Framework の歴史を振り返る - kendik.net~
http://kendik.hatenablog.com/entry/2013/05/24/033400
--Entity Framework のバージョン履歴~
https://msdn.microsoft.com/ja-jp/data/jj574253.aspx

**信任投票 [#of646cbb]

-ADO .NET Entity Framework Vote of No Confidence~
http://efvote.wufoo.com/forms/ado-net-entity-framework-vote-of-no-confidence/

-ADO.NET Entity Framework Taking Some Heat~
http://www.infoq.com/news/2008/06/entity-framework-heat

-Is ORM (Linq, Hibernate...) really that useful - Stack Overflow~
http://stackoverflow.com/questions/938524/is-orm-linq-hibernate-really-that-useful

-Entity Framework VS LINQ to SQL VS ADO.NET with stored procedures - Stack Overflow~
http://stackoverflow.com/questions/2698151/entity-framework-vs-linq-to-sql-vs-ado-net-with-stored-procedures

-データベース ファースト 恵みの波紋~
https://ogacha.wordpress.com/tag/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9-%E3%83%95%E3%82%A1%E3%83%BC%E3%82%B9%E3%83%88/

**エンプラ領域でのミスマッチ [#x151128c]
基幹系システムでは以下の理由でミスマッチと判断されることが多い。

***インピーダンス・ミスマッチ [#me452f18]
-概念モデルに対してプログラミングを採用している。
-外部スキーマを使用できないため、論理データ独立性が無い。
-概念スキーマのデータ構造を使用してプログラミングを行う必要がある。

***スキーマ構造の変更 [#g2c01a47]
-DBMSのスキーマからモデル(EDM)を生成する方法を採用している場合、~
スキーマの構造が変わった場合、モデル(EDM)の作り直しが発生する。

-生成されたモデル(EDM)をカスタマイズしていた場合、~
作り直しにより、カスタマイズが破棄されてしまう可能性がある。
--カスタマイズがなければ、概念スキーマ構造の変更を~
モデル(EDM)に同期し、変更に迅速に対応できるとも言える。
--しかし、論理データ独立性が無いため、プログラムの変更は必要になる。

-RAD開発ツールに特有の、保守性の悪さがある。~

***内部実装とその動作がブラックボックス [#xeeffcb0]
SQLが、LINQ to Entityのエンジンに生成される形であり、~
また、内部実装とその動作がブラックボックスになっているため(※1)~
それらが明確にならないと設計、チューニング、問題分析などが困難。~

従って(特に日本の)エンタープライズ・アプリケーションでは敬遠されている。~
これは、JavaのJava8でJPAでHibernateでJinqが敬遠されるのと≒。

-(※1)Questions about EntityFramework~
https://github.com/OpenTouryoProject/SampleProgram/issues/6

*参考 [#n42d5d9a]

-[[Entity Framework の調査]]

-Entity Framework のお役立ち記事まとめ ある SE のつぶやき~
http://fnya.cocolog-nifty.com/blog/2014/01/entity-frame-13.html

**@IT [#a721f612]

-.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層アーキテクチャと自己追跡エンティティ【後編】

**MSDN [#n8565ab6]
-エンティティ フレームワークの概要~
https://msdn.microsoft.com/ja-jp/library/bb399567.aspx

-Entity Framework~
https://msdn.microsoft.com/ja-jp/data/ef.aspx
--Entity Framework Development Workflows Video~
https://msdn.microsoft.com/ja-jp/data/jj590134

-雲のごとく - Site Home - MSDN Blogs~
--.NET Framework 4.5 におけるデータ アクセスの概要 その1~
http://blogs.msdn.com/b/daisukei/archive/2014/07/29/net-framework-4-5.aspx
--.NET Framework 4.5 におけるデータ アクセスの概要 その 3 ~ ADO.NET Entity Framework~
http://blogs.msdn.com/b/daisukei/archive/2014/08/29/net-framework-4-5-3-ado-net-entity-framework.aspx

--ADO.NET Entity Framework
---http://www.slideshare.net/daisukei/daisukei-ef/11
---http://www.slideshare.net/daisukei/daisukei-ef/38

----
Tags: [[:.NET開発]], [[:データアクセス]], [[:ADO.NET]], [[:Entity Framework]]

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS