「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。

-[[戻る>Entity Framework]]
--[[Entity Framework の懸念]]
--Entity Framework の調査

* 目次 [#g0ccb6ba]
#contents

*概要 [#hbe936f5]
[[Entity Framework の懸念]]に対する調査結果。

*Entity Frameworkのメモリ使用量の例 [#v08f742a]
-ユーザー定義のDbContextを生成
-SqlQueryメソッドで最小限のデータを取得
-DbContextへ格納
-DbContextのライフタイムの管理

**ユーザー定義のDbContext [#v4a65b3a]
例えば、ProductContextクラスは
-DbContextクラスから派生する必要がある。
-DbSetのプロパティを含める必要がある。
-DbSetプロパティは、コンテキストで指定されたエンティティのコレクションを表す。

 public class ProductContext : DbContext
 {
   public DbSet<Category> Categories { get; set; }
 
-Entity Framework Designer を使用している場合、~
コンテキストは、Visual Studioのテンプレートによって自動的に生成される。
-コードファーストテクニックを使用している場合は、手動でコンテキストを作成する。

**DbContextのライフタイム [#a56dc3c5]
メモリのデータ保持は、DbContextオブジェクト インスタンスのライフタイムと同じ。

以下のように、usingを使うと、ライフタイムは明確になる。

 using (ProductContext context = new ProductContext()) 
 { 
   // Perform data access using the context
 }

**SqlQueryメソッド [#u847bf98]
 using (ProductContext context = new ProductContext())
 {
   // Below code is enumerated using ToList() method. 
   // Stores all records in “myCategories” object (Memory)
   IList<Category> myCategories =
   context.Database.SqlQuery<Category>("Select * from Category").ToList();
 }

*SaveChangesメソッド使用時のコネクションやトランザクション [#h3e7ed87]
-各トランザクションのための新しい接続を作成する。
-SaveChangesメソッドが呼び出されたとき内部でトランザクションを維持する。
-一回のSaveChangesメソッドで複数エンティティ更新のトランザクションを維持する。

**Entity Framework 5.0およびそれ以前のバージョン [#o1d1991d]
***TransactionScope [#kbe4e4c3]
TransactionScopeを使用してトランザクションを処理する。

 using (EntitiesContext context = new EntitiesContext())
 {  
   using (TransactionScope scope = new TransactionScope())
   {
     //Code here
   }
 }

***手動の制御も可能 [#ia46ee17]
ASP.NET MVCでDbContextのトランザクションと~
独自SQL 処理のトランザクションを同一のスコープにする~
http://blog.makotoishida.com/2012/12/aspnet-mvcdbcontextsql.html

**Entity Framework 6.0 [#ye8d1323]
トランザクションを維持するために、2つの新しいAPIを導入している。

***DbContext.Database.BeginTransaction API [#l61d7378]
-トランザクションを開始する。
-トランザクションの分離レベルを指定することができる。
-いくつかの操作を組み合わせて、同じトランザクション内で結合することができる。~
-したがって、全てのトランザクションをコミットまたはロールバックすることができる。

 using (EntitiesContext context = new EntitiesContext())
 {
   using (var transaction = context.Database.BeginTransaction())
   {
     try
     {
       EmployeeMaster employee = new EmployeeMaster();
 
       employee.Code = "A0001";
       employee.Name = "Jignesh Trivedi";
       employee.DepartmentId = 1;
 
       context.Employees.Add(employee);
       context.SaveChanges();
 
       DepartmentMaster dept = new DepartmentMaster();
 
       dept.Code = "DEP0001";
       dept.Name = "Department 1";
 
       context.Departments.Add(dept);
       context.SaveChanges();
 
       transaction.Commit();
     }
     catch (Exception ex)
     {
       transaction.Rollback();
     }
   }
 } 

***DbContext.Database.UseTransaction API [#hb4fa611]
-Entity Framework外で明記されたトランザクションを使用するDbContextインスタンスを許可する。
-Entity Frameworkで、このAPIを使用し任意の既存トランザクションを使用することができる。

 using (SqlConnection con = new SqlConnection("connectionString"))
 {
   con.Open();
   using (var transaction = con.BeginTransaction())
   {
     // Do something....  
 
     //Pass this transaction to Entity Framework....  
     using (EntitiesContext context = new EntitiesContext(con, false))
     {
       context.Database.UseTransaction(transaction);
       EmployeeMaster employee = new EmployeeMaster();
       employee.Code = "A0001";
       employee.Name = "Jignesh Trivedi";
       employee.DepartmentId = 1;
       context.Employees.Add(employee);
 
       context.SaveChanges();
     }
   }
 } 

*ExecuteSqlCommandメソッドの実行時の挙動 [#pefceb5c]
Entity Frameworkで更新処理を実行する場合、~
基本的には、SaveChangesメソッドを使用する。

**ExecuteSqlCommand実行後、エンティティとDBは不一致状態に陥る [#sb2b27e7]
ExecuteSqlCommandメソッドは、

-コンテキスト内のエンティティの内容に関係なく、~
INSERT、UPDATE、DELETEなどのクエリを実行できる。

-このためExecuteSqlCommandメソッドの実行後は、~
エンティティとDBの内容は一致していない。

-従って、エンティティとDBの内容を一致させる必要がある場合、~
コンテキスト内のエンティティをリフレッシュする必要がある。

**エンティティをリフレッシュする方法(エンティティとDBの同期) [#f0619af5]
***エンティティをデタッチし再度問い合わせる。 [#n1f36b05]
 ((IObjectContextAdapter)context).ObjectContext.Detach(myCategory);

***Refreshメソッドでリフレッシュする。 [#db23b21b]
 ObjectContext context = ((IObjectContextAdapter)myDbContext).ObjectContext;
 // Refresh specific Entity object in the context
 context.Refresh(System.Data.Objects.RefreshMode.StoreWins, myCategory);

(OR)

 // Refresh All Entities in the context.
 var refreshableObjects = myDbContext.ChangeTracker.Entries().Select(c => c.Entity).ToList();
 context.Refresh(System.Data.Objects.RefreshMode.StoreWins, refreshableObjects);

*Entity Data Model(以下EDM)のベスト・プラクティス [#ia897808]
**更新処理 [#b078de8b]
-EDMを複数のエンティティに統合した場合、~
単一のSaveChangesメソッドの呼び出しで容易に複数のエンティティの更新が可能。
-EDMを複数のエンティティに分割した場合、~
SaveChangesメソッドを複数回呼び出す必要があり、接続とトランザクションの明示的な管理が必要。

**EDMのサイズ [#l59b2cc0]
DBに、50~100のテーブルが含まれている場合、~
すべてのエンティティを含む1つの大きなEDMを持つことは良い方法ではない。

***複数エンティティを単一EDMに結合する [#t0194656]
複数エンティティを1つの大きいEDMに集約すると、下記のようないくつかの問題を起こす。

-性能の問題
--メタデータロード時間の性能
--ビュー生成における性能

-雑然とする。
--デザイナー
--インテリセンス
--CLRネームスペース

***EDMを任意の単位に分割 [#ea8185c6]
上記を回避するため、~
ベスト・プラクティスは任意の単位にEntity Dataモデルを分割する方法である。

*動的SQLを実装する方法 [#m594ecfb]
https://github.com/OpenTouryoProject/SampleProgram/issues/3

**System.Linq.Dynamic [#v4ec2bad]
**Expression Tree [#k4607bca]
**context.Database.SqlQuery [#c5c889a2]

*参考 [#l13157a6]
**キャッシュの問題 [#d210ceb7]
-ef5 Entity Framework cache problems  Bruno Câmara~
http://www.bfcamara.com/post/37112709703/ef5-entity-framework-cache-problems

**Entity Dataモデルのサイズ [#b5abc14a]
-poco - Entity Framework 4 Does it make sense to create a single diagram for all entities - Stack Overflow~
http://stackoverflow.com/questions/3867479/entity-framework-4-does-it-make-sense-to-create-a-single-diagram-for-all-entiti/3868075

-Working With Large Models In Entity Framework – Part 1 - ADO.NET Blog - Site Home - MSDN Blogs~
http://blogs.msdn.com/b/adonet/archive/2008/11/24/working-with-large-models-in-entity-framework-part-1.aspx?wa=wsignin1.0

-Working With Large Models In Entity Framework – ADO.NET Blog - Site Home - MSDN Blogs
--http://blogs.msdn.com/b/adonet/archive/2008/11/24/working-with-large-models-in-entity-framework-part-1.aspx
--http://blogs.msdn.com/b/adonet/archive/2008/11/24/working-with-large-models-in-entity-framework-part-2.aspx

**性能 [#l09d598c]
-Tips to improve Entity Framework Performance~
http://www.dotnet-tricks.com/Tutorial/entityframework/J8bO140912-Tips-to-improve-Entity-Framework-Performance.html

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

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS