VSUG Day 2010 Summer - Using ADO.NET Entity Framework
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

VSUG Day 2010 Summer - Using ADO.NET Entity Framework

  • 7,221 views
Uploaded on

This presentataion slide describes Microsoft.NET Framework 4 ADO.NET Entity Framework and was used for VSUG Day 2010 Summer in Japan. ...

This presentataion slide describes Microsoft.NET Framework 4 ADO.NET Entity Framework and was used for VSUG Day 2010 Summer in Japan.

VSUG (Visual Studio Users Group)

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
7,221
On Slideshare
6,887
From Embeds
334
Number of Embeds
5

Actions

Shares
Downloads
73
Comments
0
Likes
2

Embeds 334

http://vsug.jp 180
http://www.slideshare.net 125
http://192.168.1.70 17
http://192.168.1.77 11
http://cache.yahoofs.jp 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. VSUG DAY 2010 Summer ADO.NET Entity Framework を使いこなそう 福井 厚 ( Twitter: @afukui ) VSUG運営委員 Microsoft Certified Architect Microsoft Regional Director Microsoft MVP for Visual C#
  • 2. 自己紹介 福井 厚 (ふくい あつし) アバナード株式会社 Group Manager / CTO Architect Visual Studio User Group 運営委員 Microsoft Certified Architect (MCA) Microsoft Regional Director Microsoft MVP for Visual Developer – C# Blog: http://www.users.gr.jp/blogs/fukui/ Twitter: @afukui VSUG DAY 2010.05.09
  • 3. 突然ですがアンケートを実施 VSUG DAY 2010.05.09
  • 4. Agenda ADO.NET Entity Frameworkとは EDM(Entity Domain Model)とは ObjectServicesとクエリ オブジェクトの追加、更新、削除 同時実行制御 エンティティ状態と変更の追跡 エンティティの継承と抽象化 N層アプリと自己追跡エンティティ まとめ VSUG DAY 2010.05.09
  • 5. 一般的な設計アプローチ ドメイン モデル、設計モデル、物理モデルの3つに分 割 ドメイン モデル  対象となるシステムに存在するエンティティとリ レーションシップを定義 設計モデル  外部キー制約を用いながら、エンティティとリレーションシッ プをテーブルとして正規化(RDBの場合) 物理モデル  パーティション分割やインデックス化などのストレージ情報を 指定することで、特定のデータ エンジンの機能に対応 VSUG DAY 2010.05.09
  • 6. 開発アプローチ ドメイン モデル駆動 概念モデルをストレートにマッピング 複雑なビジネス ロジック データベース駆動 データ中心アプローチ 既存のDBテーブルの活用 ユーザー インターフェース駆動 モックアップから開発 VSUG DAY 2010.05.09
  • 7. VSUG DAY 2010.05.09
  • 8. Entity Frameworkとは データ指向のソフトウェア アプリケー ション開発をサポートする ADO.NET のテ クノロジ セット データが格納されている、基になるデー タベース テーブルや列を意識することな く、顧客や顧客の住所など、ドメイン固 有のオブジェクトおよびプロパティの形 式でデータを扱うことが可能 EDM(後述)の実装を提供 VSUG DAY 2010.05.09
  • 9. Entity Framework Architecture Object Services Entity Domain Model ObjectContext ObjectQuery<T> Data Class CSDL EntityClient EntityConnection MSL EntityCommand EntityDataReader SSDL VSUG DAY 2010.05.09
  • 10. VSUG DAY 2010.05.09
  • 11. EDM(Entity Domain Model)とは 格納される形式に関係なく、データ構造を記述 する一連の概念 ストレージ スキーマに依存しないエンティティ とリレーションシップでデータ構造を記述 エンティティおよびリレーションシップにより アプリケーションで使用されるデータ構造 (格納 形式ではなく) が記述されるため、アプリケー ションの進化に伴ってこれらを進化させること が可能 VSUG DAY 2010.05.09
  • 12. 概念モデル、論理モデル、マッピング 概念スキーマ 定義言語(CSDL) EDMの概念を実装するDSL(Domain Specific Language)の1種 ストア スキーマ 定義言語(SSDL) マッピング 仕様言語ファイル (MSL) VSUG DAY 2010.05.09
  • 13. Entity Data Model の概念 エンティティ型  Entity Data Model でデータ構造を記述するために不可欠な構成要素  継承をサポート アソシエーション型  Entity Data Model でリレーションシップを記述するために不可欠な構 成要素  アソシエーションに含まれるエンティティ型を指定する 2 つのアソシ エーション End がある  アソシエーションのその End に存在できるエンティティ数を示すアソ シエーション End の多重度も指定する必要がある プロパティ  エンティティ型には、その構造と特性を定義するプロパティが含まれる  プロパティには、プリミティブ データ (文字列、整数、ブール値など) または構 造化データ (複合型) を含めることができる VSUG DAY 2010.05.09
  • 14. Entity Data Model でサポートされるプリミティブ データ型 プリミティブ 説明 私用できるファセット データ型 Binary バイナリ データを格納 MaxLength、FixedLength、Nullable、Default Boolean true または false Nullable、Default Byte 符号なし 8 ビット整数 Precision、Nullable、Default 値 DateTime 日時 Precision、Nullable、Default DateTimeOffset GMT からのオフセット Precision、Nullable、Default (分単位) としての日時 Decimal 有効桁数と小数点以下 Precision、Nullable、Default 桁数が固定長の数値 Double 15 桁の有効桁数を持つ Precision、Nullable、Default 浮動小数点数 Float 7 桁の有効桁数を持つ Precision、Nullable、Default 浮動小数点数 VSUG DAY 2010.05.09
  • 15. Entity Data Model でサポートされるプリミティブ データ型 プリミティブ 説明 私用できるファセット データ型 Guid 16 バイトの一意識別子 Precision、Nullable、Default Int16 符号付き 16 ビット整 Precision、Nullable、Default 数値 Int32 符号付き 32 ビット整 Precision、Nullable、Default 数値 Int64 符号付き 64 ビット整 Precision、Nullable、Default 数値 SByte 符号付き 8 ビット整数 Precision、Nullable、Default 値 String 文字データ Unicode、FixedLength、MaxLength、 Collation、Precision、Nullable、Default Time 時刻を格納 Precision、Nullable、Default VSUG DAY 2010.05.09
  • 16. アソシエーション End アソシエーションに2つのアソシエーション End アソシエーション Endの定義に含まれる情報  アソシエーションに含まれるエンティティ型  多重度(1, 0..1, *)  Endの名前  CASCADE ON DELETEなどの操作 VSUG DAY 2010.05.09
  • 17. ADO.NET Entity Data Modelの作成 VSUG DAY 2010.05.09
  • 18. VSUG DAY 2010.05.09
  • 19. Object Servicesの概要 Entity Framework ツールは、概念スキーマ定義言語 (CSDL) ファイルを使用して、オブジェクト レイヤー コードを生成  生成されるコードに含まれるデータクラス  型指定された ObjectContext クラス  エンティティ型を表し、EntityObject から継承したクラス  複合型を表し、ComplexObject から継承したクラス オブジェクト コンテキスト  以下のものをカプセル化  データベースへの接続  モデルを記述するメタデータ  作成、更新、および削除の操作時にオブジェクトを追跡する ObjectStateManager オブジェクト VSUG DAY 2010.05.09
  • 20. オブジェクト クエリ エンティティ セットを返す  ObjectQuery (.NET Framework 3.5 SP1)  ObjectSet (.NET Framework 4)  ObjectQueryクラスを拡張、型指定されたエンティティ セッ トのコンテキストでオブジェクトの追加や削除の機能を追加 using (ChinookEntities context = new ChinookEntities()) { ObjectSet<Album> albums = context.Albums; var query = from album in albums where album.Artist.Name == "Deep Purple" select new { Title = album.Title, Name = album.Artist.Name }; Console.WriteLine("Album title: "); foreach (var q in query) { Console.WriteLine(q.Name + ": " + q.Title); } … VSUG DAY 2010.05.09
  • 21. クエリを返す方法 LINQ to Entities  概念モデルで定義されているエンティティ型に対し てクエリを実行するための統合言語クエリ (LINQ) を サポート Entity SQL  SQL.ストレージに依存しない SQL 言語。概念モデル のエンティティを直接操作し、Entity Data Model の 概念をサポート クエリービルダーメソッド  LINQ スタイルのクエリ メソッドを使用して Entity SQL クエリを構成 VSUG DAY 2010.05.09
  • 22. Entity SQL Entity Framework 内の概念モデルに対するクエリの実行 に使用できる SQL に似た言語 概念モデルは、データをエンティティおよびリレーショ ンシップとして表す Entity SQL を使用すると、SQL を使用したことのある ユーザーが慣れている形式でそれらのエンティティおよ びリレーションシップに対してクエリを実行できる SELECT VALUE p.Name FROM AdventureWorksEntities.Product as p VSUG DAY 2010.05.09
  • 23. クエリービルダーメソッド ObjectQuery には、Entity SQL と等価のクエリ コマンドを順番に構築するために使用できる一 連のクエリ ビルダー メソッドも実装されている Distinct(), Except(), GroupBy(), Intersect(), OfType(), OrderBy(), Select(), SelectValue(), Skip(), Top(), Union(), UnionAll(), Where() など VSUG DAY 2010.05.09
  • 24. クエリの実行 LINQ to Entities VSUG DAY 2010.05.09
  • 25. LINQ to Entities メソッドベースの構文例(射影) using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { var query = AWEntities.Products .Select(product => new { ProductId = product.ProductID, ProductName = product.Name }); Console.WriteLine("Product Info:"); foreach (var productInfo in query) { Console.WriteLine("Product Id: {0} Product name: {1} ", productInfo.ProductId, productInfo.ProductName); } } VSUG DAY 2010.05.09
  • 26. LINQ to Entities クエリ式の構文例(射影) using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()) { ObjectSet<Product> products = AWEntities.Products; IQueryable<Product> productsQuery = from product in products select product; Console.WriteLine("Product Names:"); foreach (var prod in productsQuery) { Console.WriteLine(prod.Name); } } VSUG DAY 2010.05.09
  • 27. LINQ to Entities クエリ式の構文例(フィルター処理) ObjectSet<SalesOrderHeader> orders = AWEntities.SalesOrderHeaders; var onlineOrders = from order in orders where order.OnlineOrderFlag == true select new { SalesOrderID = order.SalesOrderID, OrderDate = order.OrderDate, SalesOrderNumber = order.SalesOrderNumber }; VSUG DAY 2010.05.09
  • 28. LINQ to Entities クエリ式の構文例(集計演算子処理) ObjectSet<Product> products = AWEntities.Products; var query = from product in products group product by product.Style into g select new { Style = g.Key, AverageListPrice = g.Average(product => product.ListPrice) }; foreach (var product in query) { Console.WriteLine("Product style: {0} Average list price: {1}", product.Style, product.AverageListPrice); } VSUG DAY 2010.05.09
  • 29. LINQ to Entities クエリ式の構文例(パーティション分割) var query = (from album in albums where album.Artist.Name == "Deep Purple" orderby album.Title select new { Title = album.Title, Name = album.Artist.Name }).Take(3); VSUG DAY 2010.05.09
  • 30. LINQ to Entities クエリ式の構文例(結合演算子) GroupJoin() 左外部結合に相当 var query = from contact in contacts join order in orders on contact.ContactID equals order.Contact.ContactID into contactGroup select new { ContactID = contact.ContactID, OrderCount = contactGroup.Count(), Orders = contactGroup.Select(order => order) }; VSUG DAY 2010.05.09
  • 31. LINQ to Entities クエリ式の構文例(グループ化) var query = ( from contact in contacts group contact by contact.LastName.Substring(0, 1) into contactGroup select new { FirstLetter = contactGroup.Key, ContactGroup = contactGroup }). OrderBy(letter => letter.FirstLetter); foreach (var contact in query) { Console.WriteLine("Last names that start with the letter '{0}':", contact.FirstLetter); foreach (var name in contact.ContactGroup) { Console.WriteLine(name.LastName); } } VSUG DAY 2010.05.09
  • 32. 関連オブジェクトの読み込み 読み込みパターン 説明 クエリで指定する ナビゲーション プロパティを使用 明示的読み込み Loadメソッドを使用 遅延読み込み LazyLoadingEnabledプロパティをtrueにセット 一括読み込み ObjectQuery で Include(String) メソッドを使用 VSUG DAY 2010.05.09
  • 33. 関連するオブジェクトを明示的に読み込む Contact customer = context.Contacts .Where("it.ContactID = @customerId", new ObjectParameter("customerId", customerId)).First(); if (!customer.SalesOrderHeaders.IsLoaded) { customer.SalesOrderHeaders.Load(); } foreach (SalesOrderHeader order in customer.SalesOrderHeaders) { if (!order.SalesOrderDetails.IsLoaded) { order.SalesOrderDetails.Load(); } VSUG DAY 2010.05.09
  • 34. 遅延読み込み Entity Framework ツールを使用して新しいモデルおよび 対応する生成済みクラスを作成する場合、 LazyLoadingEnabled の既定値は true context.ContextOptions.LazyLoadingEnabled = true; 遅延読み込みは、単一オブジェクト (EntityReference な ど) とオブジェクトのコレクション (EntityCollection な ど) の両方を返すナビゲーション プロパティでサポート 遅延読み込みが有効であっても、関連オブジェクトが既 に読み込まれているなら、関連オブジェクトが再度読み 込まれることはない 遅延読み込みは、Detached() 状態にあるオブジェクトで サポートされる。この場合、関連オブジェクトも Detached() 状態で返される VSUG DAY 2010.05.09
  • 35. 一括読み込み(クエリ パスの定義) var contacts = (from contact in context.Contacts .Include("SalesOrderHeaders.SalesOrderDetails") select contact).FirstOrDefault(); try { foreach (SalesOrderHeader order in contacts.SalesOrderHeaders) { Console.WriteLine(String.Format("PO Number: {0}", order.PurchaseOrderNumber)); Console.WriteLine(String.Format("Order Date: {0}", order.OrderDate.ToString())); Console.WriteLine("Order items:"); foreach (SalesOrderDetail item in order.SalesOrderDetails) { Console.WriteLine(String.Format("Product: {0} " + "Quantity: {1}", item.ProductID.ToString(), item.OrderQty.ToString())); } } VSUG DAY 2010.05.09
  • 36. VSUG DAY 2010.05.09
  • 37. オブジェクトの作成と追加 using (ChinookEntities context = new ChinookEntities()) { ObjectSet<Artist> artists = context.Artists; //ArtistIdはIdentityとして宣言されているので、初期値(0)は無視される Artist artist = Artist.CreateArtist(0); artist.Name = "Atsushi Fukui"; artists.AddObject(artist); context.SaveChanges(); Console.WriteLine("Added Artist id {0} name {1}", artist.ArtistId, artist.Name); VSUG DAY 2010.05.09
  • 38. オブジェクトの削除 using (ChinookEntities context = new ChinookEntities()) { ObjectSet<Artist> artists = context.Artists; Artist artist = artists.Where("it.Name=@name", new ObjectParameter("name", "Atsushi Fukui")).First(); if (artist != null) { artists.DeleteObject(artist); context.SaveChanges(); } } VSUG DAY 2010.05.09
  • 39. オブジェクトの更新 object entity = null; IEnumerable<KeyValuePair<string, object>> keyValues = new KeyValuePair<string, object>[]{ new KeyValuePair<string, object>("ArtistId", 279) }; EntityKey key = new EntityKey("ChinookEntities.Artists", keyValues); if (context.TryGetObjectByKey(key, out entity)) { Artist artist = (Artist)entity; artist.Name = "Hideharu Moriya"; context.SaveChanges(); } Artist a = context.Artists.Where(o => o.ArtistId == 279).First(); if (a != null) { Console.WriteLine(“artist id {0}, name {1}”, a.ArtistId, a.Name); } VSUG DAY 2010.05.09
  • 40. ID管理、状態管理、変更の追跡 ObjectStateEntry  アタッチされている各オブジェクトに対して作成さ れる  EntityKey と EntityState、関連するオブジェクトに関 する情報、およびオブジェクトのプロパティの元の 値と現在の値を格納  エンティティがデタッチされると、対応する ObjectStateEntry オブジェクトがオブジェクト コンテ キストから削除される  ObjectStateManager によって管理される  各オブジェクト コンテキストについて、 ObjectStateManager のインスタンスが 1 つ存在 VSUG DAY 2010.05.09
  • 41. エンティティ状態 マージ 説明 オプション Added 新しいオブジェクトがオブジェクト コンテキストに追加されている。 SaveChanges() メソッドは呼び出されていない。変更が保存されると、 オブジェクトの状態は Unchangedに変更される。 Deleted オブジェクトがオブジェクト コンテキストから削除されている。変更 が保存されると、オブジェクトの状態は Detachedに変更される。 Detached オブジェクトが存在するが追跡されていない。エンティティは、作成さ れた直後とオブジェクト コンテキストに追加される直前にこの状態に なる。また、Detach(Object) メソッドを呼び出してコンテキストから削 除された後、または NoTracking MergeOption を使用して読み込まれる 場合にもこの状態になる。 Modified オブジェクトのスカラー プロパティのいずれかが変更されている。 SaveChangesメソッドは呼び出されていない。変更追跡プロキシを持た ない POCO エンティティでは、DetectChangesメソッドが呼び出された ときに、変更されているプロパティの状態が Modified に変わる。変更 が保存されると、オブジェクトの状態は Unchangedに変わる。 Unchanged オブジェクトは、コンテキストに読み込まれた後、または最後に SaveChanges メソッドが呼び出されてから変更されていない。 VSUG DAY 2010.05.09
  • 42. 変更の追跡 Entity Framework により生成されたエンティティおよび変更追跡プ ロキシ オブジェクトを持つ POCO エンティティに対しては、 ObjectStateEntry はオブジェクト プロパティの現在の値および変更 されたプロパティの元の値を格納する Added 状態または Detached 状態にあるオブジェクトは、元の値を 保持していない オブジェクト コンテキストは、プロパティが変更されると通知を受 け取り、ObjectStateEntry 内のオブジェクトの状態とプロパティの 値を更新する ObjectStateEntry は、変更追跡プロキシの無いPOCOエンティティ、 および複合型オブジェクトでは異なる方法で管理する。これらの型 のオブジェクトに対し、ObjectStateEntryは、オブジェクトが最初 にコンテキストに入った時にオブジェクト プロパティの値のスナッ プショットを取得し、元の値のセットと現在の値のセットを格納す る。 VSUG DAY 2010.05.09
  • 43. ID解決とマージ 特定のエンティティ キーを持つオブジェクトの 1 つのみのインスタンスをキャッシュ内に保持 する 同じ ID を持つエンティティが既に追跡されてい る場合、データ ソースからのデータと状態マ ネージャーに既に存在するデータは、クエリの MergeOption に従ってマージされる var orders = Customer.Orders.Execute(MergeOption.PreserveChanges); VSUG DAY 2010.05.09
  • 44. マージ オプション マージ オプション 説明 AppendOnly オブジェクト コンテキストに存在しないオブジェクトは、コンテキストに アタッチされる。オブジェクト コンテキストに存在するオブジェクトのプ ロパティは、データ ソースの値によって上書きされない。AppendOnly() は既定のマージ オプション OverwriteChanges オブジェクト コンテキストに存在しないオブジェクトは、コンテキストに アタッチされる。オブジェクト コンテキストに存在するオブジェクトのプ ロパティは、データ ソースの値によって上書きされる。 PreserveChanges .NET Framework バージョン 3.5 SP1 では、オブジェクト コンテキスト内 のオブジェクトのプロパティ値がサーバー上の値と異なる場合、オブジェ クト コンテキスト内のプロパティ値は、オブジェクトが Unchanged状態 にない限り、保持される。Unchanged状態の場合は、プロパティがデータ ソースの値で上書きされる。 .NET Framework バージョン 4 では、オブジェクト コンテキスト内のオブ ジェクトの値はすべて、オブジェクトの状態にかかわらず保持される。 NoTracking オブジェクトは、Detached状態で保持され、ObjectStateManager では追 跡されない。ただし、Entity Framework により生成されたエンティティお よびプロキシを持つ POCO エンティティは、関連するオブジェクトの読み 込みを容易にするために、オブジェクト コンテキストへの参照を保持する。 VSUG DAY 2010.05.09
  • 45. 同時実行制御チェック ConcurrencyMode=“Fixed” を使用すると Entity Framework は、変更をデータベース に保存する前に、データベース内の変更 をチェックする SQL Serverの場合、各テーブルにタイムス タンプ列を追加して指定すると良い 他のデータベースの場合はトリガでタイムス タンプを更新するなど VSUG DAY 2010.05.09
  • 46. 同時実行制御チェック VSUG DAY 2010.05.09
  • 47. VSUG DAY 2010.05.09
  • 48. Entity Data Model: 継承 概念モデルでは派生型は基本型のすべてのプロ パティとナビゲーション プロパティを継承 ルート型はエンティティ キーを定義する必要が ある 単一継承のみ可能 CSDLによる定義例 <EntityType Name="FictionBook" BaseType="BooksModel.Book" > <Property Type="String" Name="Genre" Nullable="false" /> </EntityType> VSUG DAY 2010.05.09
  • 49. 概念モデルの継承の実装方式 Table-Per-Type継承  概念スキーマで派生型のBaseType属性に基本エンティティ型を 指定  基本エンティティを抽象型として定義  派生型のIDを削除  マッピングの詳細ウィンドウでIDを基本エンティティのIDに マップ Table-Per-Hierarchy 継承  概念スキーマで派生型のBaseType属性に基本エンティティ型を 指定  マッピングの詳細ウィンドウで「テーブルまたはビューの追 加」からテーブルを選択  条件の追加でプロパティにIs NullまたはIs Not Nullを設定 VSUG DAY 2010.05.09
  • 50. 自動生成されるSQLの一部 -- Creating table 'Parties' CREATE TABLE [dbo].[Parties] ( [Id] int IDENTITY(1,1) NOT NULL, [Name] nvarchar(max) NOT NULL ); GO -- Creating table 'Parties_Organization' CREATE TABLE [dbo].[Parties_Organization] ( [Location] nvarchar(max) NOT NULL, [Id] int NOT NULL ); GO -- Creating table 'Parties_Person' CREATE TABLE [dbo].[Parties_Person] ( [Age] int NOT NULL, [Id] int NOT NULL ); GO VSUG DAY 2010.05.09
  • 51. エンティティの継承 VSUG DAY 2010.05.09
  • 52. VSUG DAY 2010.05.09
  • 53. N層アプリケーションとは クライアント層、中間サービス層、デー タベース層に分かれる ASP.NETアプリケーション WCFサービス、Webサービスを利用するアプ リケーション Silverlightアプリケーション オブジェクトをシリアル化して他の層に 転送し逆シリアル化して利用 更新された情報を何らかの方法で保持す る必要がある VSUG DAY 2010.05.09
  • 54. オブジェクトのシリアル化 オブジェクトをシリアル化すると、EntityKey オブジェクトもシリ アル化される バイナリ シリアル化と WCF データ コントラクト シリアル化を使 用する場合に、シリアル化するオブジェクトのオブジェクト グラフ に関連オブジェクトがあると、これらのオブジェクトもシリアル化 される XML シリアル化では、関連オブジェクトはシリアル化されない オブジェクトのプロパティとリレーションシップ情報だけがシリア ル化される オブジェクト コンテキストで維持されているオブジェクトの状態情 報はシリアル化されない .NET Framework バージョン 4 から、自己追跡エンティティで独自 の変更追跡ロジックを利用できるようになった(後述) オブジェクトが逆シリアル化された後、オブジェクトは Detached() 状態になる VSUG DAY 2010.05.09
  • 55. オブジェクトのアタッチ、デタッチ Entity Framework では、オブジェクト コンテキスト内で クエリを実行すると、返されたオブジェクトがそのオブ ジェクト コンテキストに自動的にアタッチされる 以前にデタッチされているオブジェクト、NoTracking() クエリによって返されたオブジェクト、またはオブジェ クト コンテキストの外部で取得したオブジェクトなど もアタッチできる ASP.NET アプリケーションのビュー ステートに保存さ れていたオブジェクトや、リモート メソッド呼び出し または Web サービスによって返されたオブジェクトも アタッチできる VSUG DAY 2010.05.09
  • 56. 変更の適用(デタッチ オブジェクト) 単純にアタッチされた場合、そのオブジェクト が既にオブジェクト コンテキスト内にあると、 更新が失われるか、操作が失敗する (Unchanged状態でアタッチされるため) オリジナルのオブジェクトと変更後のオブジェ クトをクライアントから返してもらうことでオ ブジェクト コンテキストにアタッチしたオブ ジェクトに変更を適用する VSUG DAY 2010.05.09
  • 57. オブジェクトをアタッチするメソッド メンバー 説明 ObjectSetAddObject() オブジェクトとその関連オブジェクトを ObjectContext または に追加し、エンティティ オブジェクトを Added 状態に ObjectContextAddObject(S 設定します。この状態では、エンティティ オブジェクト tring, Object) の一意のキー値を持つ必要はない。一時的なキー値が キーのプロパティに割り当てられ、オブジェクトの保存 後にデータ ソースが生成した値で更新される。オブジェ クトを追加後、エンティティ オブジェクトの状態が適切 に変更される。 ObjectSetAttach() オブジェクトを ObjectContext に追加し、オブジェクト または を Unchanged 状態に設定する。Unchanged 状態では、 ObjectContextAttach(IEntit Entity Framework はエンティティ キーの値を最終版とし yWithKey) て処理する。特定の型の複数のエンティティに同じキー と の値がある場合は、Entity Framework は例外をスローす AttachTo(String, Object) る。例外を回避するには、AddObject メソッドを使用し てデタッチされたオブジェクトをアタッチし、適切な状 態に変更する。 VSUG DAY 2010.05.09
  • 58. アタッチして変更を適用する例 private static void ApplyItemUpdates( SalesOrderDetail originalItem, SalesOrderDetail updatedItem) { using (AdventureWorksEntities advWorksContext = new AdventureWorksEntities()) { try { //オリジナルのItemをオブジェクト コンテキストにアタッチ advWorksContext.Attach(originalItem); //変更を適用するためにApplyCurrentValuesメソッドを使用 advWorksContext.ApplyCurrentValues(“SalesOrderDetails”, updatedItem); advWorksContext.SaveChanges(); } catch (InvalidOperationException ex) { Console.WriteLine(ex.ToString()); } } } VSUG DAY 2010.05.09
  • 59. 自己追跡エンティティ VSUG DAY 2010.05.09
  • 60. 自己追跡エンティティ //クライアント側コード static void UpdateDepartmentAndCourses(int departmentID, int courseID) { using (var service = new Service1Client()) { List<Department> departments = service.GetDepartments(); Department department = departments.Single( d => d.DepartmentID == departmentID); department.Budget = department.Budget - 1000.00m; Course existingCourse = department.Courses.Single( c => c.CourseID == courseID); existingCourse.Credits = 3; service.UpdateDepartment(department); } } VSUG DAY 2010.05.09
  • 61. 自己追跡エンティティ //サービス側コード public void UpdateDepartment(Department updated) { using (SchoolEntities context = new SchoolEntities()) { try { context.Departments.ApplyChanges(updated); context.SaveChanges(); } catch (UpdateException) { throw; } } } VSUG DAY 2010.05.09
  • 62. まとめ ADO.NET Entity FrameworkはEDMの実装を提供 概念スキーマ定義とストア スキーマ定義をマッピング することでストアに非依存なモデルを利用可能  エンティティとアソシエーションの概念 同時実行制御チェックを有効にする オブジェクト状態を理解する N層アプリケーションと自己追跡エンティティ  WCF サービス アプリケーションとの連携  ObjectContextをサービス層でキャッシュするのはアンチパタン 継承エンティティによるテーブル マッピング その他  IObjectSetの利用によってテスト容易性が向上している VSUG DAY 2010.05.09
  • 63. 参考資料 Entity Framework を使用した n 層アプリケーションで回 避すべきアンチパターン http://msdn.microsoft.com/ja-jp/magazine/dd882522.aspx n 層アプリケーションのパターン http://msdn.microsoft.com/ja-jp/magazine/ee321569.aspx チュートリアル: ストアド プロシージャへのエンティ ティのマッピング http://msdn.microsoft.com/ja-jp/library/cc716679(v=VS.100).aspx Walkthrough: Serialize Self-Tracking Entities (Entity Framework) (英語) http://msdn.microsoft.com/en-us/library/ee789839(v=VS.100).aspx Entity Framework FAQ(英語) http://blogs.msdn.com/dsimmons/pages/entity-framework-faq.aspx VSUG DAY 2010.05.09
  • 64. VSUG DAY 2010.05.09
  • 65. Appendix VSUG DAY 2010.05.09
  • 66. EdmGen.exe コマンドラインによるオブジェクト レイ ヤ生成 C#のコード生成 "%windir%¥Microsoft.NET¥Framework¥v4.0.30319¥edmgen.exe" /mode:EntityClassGeneration /incsdl:.¥School.csdl /outobjectlayer:.¥School.Objects.cs /language:CSharp VBのコード生成 "%windir%¥Microsoft.NET¥Framework¥v4.0.30319¥edmgen.exe" /mode:EntityClassGeneration /incsdl:.¥School.csdl /outobjectlayer:.¥School.Objects.vb /language:VB VSUG DAY 2010.05.09
  • 67. 概念スキーマ 定義言語: EntityContainer … <EntityContainer Name="ChinookEntities“ annotation:LazyLoadingEnabled="true"> <EntitySet Name="Albums" EntityType="ChinookModel.Album" /> <EntitySet Name="Artists" EntityType="ChinookModel.Artist" /> <AssociationSet Name="FK__Album__ArtistId__108B795B“ Association="ChinookModel.FK__Album__ArtistId__108B795B" > <End Role="Artist" EntitySet="Artists" /> <End Role="Album" EntitySet="Albums" /> </AssociationSet> </EntityContainer> … VSUG DAY 2010.05.09
  • 68. 概念スキーマ 定義言語: EntityType … <EntityType Name="Album"> <Key> <PropertyRef Name="AlbumId" /> </Key> <Property Name="AlbumId" Type="Int32" Nullable="false" annotation:StoreGeneratedPattern="Identity" /> <Property Name="Title" Type="String" Nullable="false" MaxLength="160" Unicode="true" FixedLength="false" /> <Property Name="ArtistId" Type="Int32" Nullable="false" /> <NavigationProperty Name="Artist“ Relationship="ChinookModel.FK__Album__ArtistId__108B795B“ FromRole="Album" ToRole="Artist" /> </EntityType> … VSUG DAY 2010.05.09
  • 69. 概念スキーマ 定義言語: Association … <Association Name="FK__Album__ArtistId__108B795B"> <End Type="ChinookModel.Artist" Role="Artist" Multiplicity="1" /> <End Type="ChinookModel.Album" Role="Album" Multiplicity="*" /> <ReferentialConstraint> <Principal Role="Artist"> <PropertyRef Name="ArtistId" /> </Principal> <Dependent Role="Album"> <PropertyRef Name="ArtistId" /> </Dependent> </ReferentialConstraint> </Association> … VSUG DAY 2010.05.09
  • 70. ストア スキーマ 定義言語: EntityContainer … <EntityContainer Name="ChinookModelStoreContainer"> <EntitySet Name="Album“ EntityType="ChinookModel.Store.Album" store:Type="Tables" Schema="dbo" /> <EntitySet Name="Artist" EntityType="ChinookModel.Store.Artist" store:Type="Tables" Schema="dbo" /> <AssociationSet Name="FK__Album__ArtistId__108B795B" Association="ChinookModel.Store.FK__Album__ArtistId__108B7 95B"> <End Role="Artist" EntitySet="Artist" /> <End Role="Album" EntitySet="Album" /> </AssociationSet> </EntityContainer> … VSUG DAY 2010.05.09
  • 71. ストア スキーマ 定義言語: EntityType … <EntityType Name="Album"> <Key><PropertyRef Name="AlbumId" /></Key> <Property Name="AlbumId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> <Property Name="Title" Type="nvarchar" Nullable="false" MaxLength="160" /> <Property Name="ArtistId" Type="int" Nullable="false" /> </EntityType> <EntityType Name="Artist"> <Key><PropertyRef Name="ArtistId" /></Key> <Property Name="ArtistId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> <Property Name="Name" Type="nvarchar" MaxLength="120" /> </EntityType> … VSUG DAY 2010.05.09
  • 72. ストア スキーマ 定義言語: Association … <Association Name="FK__Album__ArtistId__108B795B"> <End Role="Artist" Type="ChinookModel.Store.Artist" Multiplicity="1" /> <End Role="Album" Type="ChinookModel.Store.Album" Multiplicity="*" /> <ReferentialConstraint> <Principal Role="Artist"> <PropertyRef Name="ArtistId" /> </Principal> <Dependent Role="Album"> <PropertyRef Name="ArtistId" /> </Dependent> </ReferentialConstraint> </Association> … VSUG DAY 2010.05.09
  • 73. マッピング 仕様言語: EntityMapping … <EntitySetMapping Name="Albums"> <EntityTypeMapping TypeName="ChinookModel.Album"> <MappingFragment StoreEntitySet="Album"> <ScalarProperty Name="AlbumId" ColumnName="AlbumId" /> <ScalarProperty Name="Title" ColumnName="Title" /> <ScalarProperty Name="ArtistId" ColumnName="ArtistId" /> </MappingFragment> </EntityTypeMapping> </EntitySetMapping> … VSUG DAY 2010.05.09
  • 74. データベースへの接続 以下の場合に自動的に接続  ObjectContext に対する SaveChanges()、または Refresh(RefreshMode, IEnumerable)  ObjectQuery に対する FirstOrDefault(IEnumerable<UMP>)、ま たは First(IEnumerable<UMP>)  EntityCollection に対する Load(MergeOption)  EntityReference に対する Load(MergeOption)  任意の統合言語クエリ (LINQ) メソッドまたは ObjectQuery クエ リ ビルダー メソッド (Where(String, ObjectParameter[])、 OrderBy(String, ObjectParameter[])、Select(String, ObjectParameter[]) など)  接続は、ObjectResult が完全に消費されるか破棄されるまで開 いたままになる VSUG DAY 2010.05.09
  • 75. 接続を手動で開く using (AdventureWorksEntities advWorksContext = new AdventureWorksEntities()) { try { //明示的に接続を開く advWorksContext.Connection.Open(); // オーダーを返すクエリを実行 SalesOrderHeader order = advWorksContext.SalesOrderHeaders.Where( "it.SalesOrderID = @orderId", new ObjectParameter("orderId", orderId)) .Execute(MergeOption.AppendOnly).First(); order.Status = 1; // 変更を保存 if (0 < advWorksContext.SaveChanges()) { Console.WriteLine("Changes saved."); } } catch (InvalidOperationException ex) { Console.WriteLine(ex.ToString()); } // オブジェクト コンテキストがDisposeされるときに接続は閉じられる } VSUG DAY 2010.05.09