第3部 sql server...

70
1 第 3 部 SQL Server データゕクセス手法(3) ADO.NET Entity Framework

Upload: others

Post on 19-Aug-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

1

第 3 部 SQL Server データゕクセス手法(3)

ADO.NET Entity Framework 編

Page 2: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

2

このドキュメントに記載されている情報 (URL 等のンターネット Web サトに関する情報を含む) は、将来予告なしに変更

することがあります。このドキュメントに記載された内容は情報提供のみを目的としており、明示または黙示に関わらず、こ

れらの情報についてマクロソフトはいかなる責任も負わないものとします。

お客様が本製品を運用した結果の影響については、お客様が負うものとします。お客様ご自身の責任において、適用されるす

べての著作権関連法規に従ったご使用を願います。このドキュメントのいかなる部分も、米国 Microsoft Corporation の書面に

よる許諾を受けることなく、その目的を問わず、どのような形態であっても、複製または譲渡することは禁じられています。

ここでいう形態とは、複写や記録など、電子的な、または物理的なすべての手段を含みます。

マクロソフトは、このドキュメントに記載されている内容に関し、特許、特許申請、商標、著作権、またはその他の無体財

産権を有する場合があります。別途マクロソフトのラセンス契約上に明示の規定のない限り、このドキュメントはこれら

の特許、商標、著作権、またはその他の無体財産権に関する権利をお客様に許諾するものではありません。

別途記載されていない場合、このソフトウェゕおよび関連するドキュメントで使用している会社、組織、製品、ドメン名、

電子メールゕドレス、ロゴ、人物、出来事などの名称は架空のものです。実在する会社名、組織名、商品名、個人名などとは

一切関係ありません。

© 2010 Microsoft Corporation. All rights reserved.

Microsoft、Windows、MSDN、SQL Server、Visual Basic、Visual C++、Visual C#、Visual Studio は、米国 Microsoft

Corporation の米国およびその他の国における登録商標または商標です。

記載されている会社名、製品名には、各社の商標のものもあります。

Page 3: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

3

目次

はじめに ............................................................................................................................................................... 4

前提知識 .............................................................................................................................................................................................. 4

ENTITY FRAMEWORK の基本的な利用方法 ..................................................................................................... 6

データモデリングの手法 ............................................................................................................................................................. 6

プログラミングの手法 ............................................................................................................................................................... 10

ビジュアルなモデリング環境と OBJECTCONTEXT ...................................................................................... 16

Entity Data Model デザナーと Entity Data Model ウゖザードの基本操作 ...................................................... 16

ナビゲーションプロパテゖの利用 ........................................................................................................................................ 24

継承の利用 ...................................................................................................................................................................................... 31

モデルフゔーストによるデザン ........................................................................................................................................ 40

ENTITY FRAMEWORK の更新とトランザクション ...................................................................................... 54

ObjectContext による更新 ....................................................................................................................................................... 54

ObjectContext と TransactionScope を使用した同時実行制御 ................................................................................ 57

ENTITY FRAMEWORK のデータバインディング .......................................................................................... 59

クエリ結果へのバンデゖング ............................................................................................................................................ 59

ObjectContext のオブジェクトとのバンデゖング .................................................................................................... 60

オプテゖミステゖック同時実行制御における操作 ....................................................................................................... 63

まとめ ................................................................................................................................................................ 70

Page 4: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

4

はじめに

この第 3 部の ADO.NET Entity Framework 編では、ADO.NET Entity Framework を用いた具体的な実装

方法や Visual Studio 2010 の使用方法について取り上げます。ADO.NET 編や LINQ 編と同様に、実際

のゕプリケーションの中で、データゕクセステクノロジをどう活用するのかを確認していただくため

に、予め完成してある AWSC サンプルプログラムを題材にします。サンプルプログラムの中から、

重要なコードの実装例や、そのコードに至る Visual Studio の操作のポントなどを確認します。ま

た、バリエーションとして、一部のサンプルについては、簡単なものを新規に作成して、動作を確認

します。

この ADO.NET Entity Framework 編では、まず、第 2 部で列挙したいくつかの実装方法の選択肢につ

いて、基本的な操作方法や具体的な実装手段の特徴を確認します。そのあと、第 2 部で紹介した

EDM デザナーで構築する ObjectContext の利用方法や、ObjectContext を用いた更新のほか、接続

型の操作であるトランザクション、そして、データバンデゖングや、その元のデータとなる非接続

型データキャッシュのオプテゖミステゖック同時実行制御などを扱います。

ここでも、テクノロジが提供するすべての機能を網羅的に解説するわけではありませんが、ここで取

り上げたことは、今後、開発者のみなさんがデータゕクセステクノロジを使用して実装する際に、そ

れらを使いこなす上での「着眼点」や「指針」、「コツ」など得ることができるでしょう。また、こ

こで取り上げる実装例は、.NET Framework 4 を前提にしており、このバージョン 4 に対応した

ADO.NET Entity Framework の新機能の中で、主だったものをいくつか使用しています。

註: .NET Framework 4 における ADO.NET Entity Framework の新機能全般については、以下のゕド

レスを参照してください。

http://msdn.microsoft.com/ja-jp/library/ex6y04yf.aspx ADO.NET の新機能

なお、AWSC サンプルプログラムのセットゕップ方法は、別途、「AWSC サンプルセットゕップガ

ド」をご参照ください。

また、この AWSC サンプルプログラムの基本的な構成が、ADO.NET 編「はじめに」の中の、

「AWSC サンプルプログラムの特徴」に記載されています。併せてご覧ください。

前提知識

サンプルを動作確認するにあたり、Visual Studio の基本的な操作手順等については割愛しており、当

ドキュメントに沿って操作する上での前提知識として必要になります。また、ソースコード例の解説

では、紙面の都合もあり、そのコードの特徴的な部分に焦点を当てて説明しています。そのため、基

本的な言語文法の知識も前提として必要になります。

サンプルは主に Visual Basic で記載されていますが、C# や C++、Java などのいずれかのオブジェク

ト指向プログラミング言語の知識をお持ちであれば、サンプルコードの内容は想像がつくでしょう。

Page 5: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

5

具体的な前提知識としては、主に以下の事項に関して必要となります。

Visual Studio のソリューションやプロジェクトを開くことができる。また、ソリューション

とプロジェクトの違いを理解している。

Visual Studio の統合開発環境で使用するウゖンドウ、たとえば、フォームデザナーやコー

ドエデゖターなど、特定の機能のウゖンドウを開くことができる。

ビルドやデバッグの実行方法や、Web ゕプリケーションの実行方法が分かる。

1 つのプロジェクトから、別のプロジェクトを参照するための「参照の追加」(参照設定) を

行うことができる。

SQL Server Management Studio、または、Visual Studio などを使用して、SQL Server データ

ベースに格納されたデータを確認できる。

Visual Basic、または C#、C++ などのオブジェクト指向言語の基本的な文法が理解できる。

特に、クラスラブラリを使用する上での、ンスタンスの作成やメソッド呼び出し、プロ

パテゖの参照や設定など。

なお、第 1 部、および第 2 部では、ADO.NETEntity Framework の基本的な特徴について既に確認して

います。主に、次に挙げる各項を取り上げました。これらの各項目については、第 1 部の「モデリン

グに向けた強化」、および第 2 部の「ADO.NET Entity Framework オーバービュー」を参照してくだ

さい。

エンテゖテゖデータモデル (EDM) の特徴と、概念モデル、ストレージモデル、およびマッピ

ングの関係 (第 1 部)

Entity Framework 向けデータプロバダーの使用方法の特徴、Entity SQL の特徴 (第 2 部)

EDM、データプロバダー、Object Services、および LINQ to Entities のそれぞれの特徴と相

互関係 (第 2 部)

ObjectContext の基本的な役割 (第 2 部)

Page 6: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

6

Entity Framework の基本的な利用方法

この節では、ADO.NET Entity Framework (以降は Entity Framework と表記) の基本的な利用方法を改

めて確認します。既に触れたように、Entity Framework では、エンテゖテゖデータモデル (EDM:

Entity Data Model) と呼ばれるデータモデルに基づき、データ操作のためのプログラミングを行いま

す。ここでは、まず、そのようなモデルを構築するための、モデリング手法として Entity Framework

が提供する機能を確認し、さらに、具体的なデータゕクセス手段である、データプロバダーや

Object Services、LINQ to Entities について、基本的な実装コード例をもとに、その特徴を確認します。

なお、ここでも必要に応じて AWSC サンプルプログラムを使用するので、ソースコードや動作の確

認がすぐに出来るよう準備しておいてください。特に、AWWinApp ゕプリケーション (AWSol-A.sln)

を使用します。

データモデリングの手法

第 1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

立した概念モデル (①) のエンテゖテゖを定義し、それをプログラム上のオブジェクトにマップしま

す。そして、別途、物理的なストレージに対応するストレージモデル (③) を定義して、概念モデル

とマッピング (②) を行います。そのため、図にあるように 3 種類の定義を行う必要があります。

図 1. 再掲: エンティティデータモデル (EDM)

この 3 種類の定義は、上図にあるように、CSDL、MSL、および SSDL と呼ばれる定義言語を使用して、

定義します。この定義言語は、予約された名前を持つ XML 要素と構造からなる言語です。たとえば、

実際のストレージ

①概念モデル問題領域の概念的なエンテゖテゖやリレーションの定義

②マッピング両モデル間の対応付け

③ストレージモデル特定のデータソースに基づく論理スキーマのモデル

プログラム上のオブジェクト

定義言語:

概念モデル→ 概念スキーマ定義言語 (Conceptual schema:CSDL)

マッピング→ マッピング仕様言語 (Mapping Specification:MSL)

ストレージモデル→ストゕスキーマ定義言語 (Storage schema:SSDL )

マップ

ソフトウェゕ開発者は、概念モデルのエンテゖテゖとオブジェクトとの間でマッピングを行う。

Page 7: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

7

「Sales」という名前の データベースに、以下のように定義された「商品コード」と「商品名」の列

を持つ「商品」テーブルがあるとします。

CREATE TABLE [商品](

[商品コード] int NOT NULL,

[商品名] nvarchar(20) NOT NULL

CONSTRAINT [PK_商品] PRIMARY KEY ( [商品コード] ))

これにゕクセスするために、概念モデルとストレージモデルを定義し、両者のマッピングを行うと、

次のようになります。(紙面の都合で、一部途中改行しています。)

例 1. (参考) 概念スキーマ定義言語 (CSDL)

<?xml version="1.0" encoding="utf-8"?> <Schema Namespace="SalesModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2006/04/edm"> <EntityContainer Name="SalesEntities"annotation:LazyLoadingEnabled="true"> <EntitySet Name="商品" EntityType="SalesModel.商品" /> </EntityContainer> <EntityType Name="商品"> <Key> <PropertyRef Name="商品コード" /> </Key> <Property Name="商品コード" Type="Int32" Nullable="false" /> <Property Name="商品名" Type="String" Nullable="false" MaxLength="20" Unicode="true" FixedLength="false" /> </EntityType> </Schema>

例 2. (参考) ストアスキーマ定義言語 (SSDL)

<?xml version="1.0" encoding="utf-8"?> <Schema Namespace="SalesModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm /EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl"> <EntityContainer Name="SalesModelStoreContainer"> <EntitySet Name="商品" EntityType="SalesModel.Store.商品" store:Type="Tables" Schema="dbo" /> </EntityContainer> <EntityType Name="商品"> <Key> <PropertyRef Name="商品コード" /> </Key> <Property Name="商品コード" Type="int" Nullable="false" /> <Property Name="商品名" Type="nvarchar" Nullable="false" MaxLength="20" /> </EntityType> </Schema>

Page 8: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

8

例 3. (参考) マッピング仕様定義言 (MSL)

<?xml version="1.0" encoding="utf-8"?> <Mapping Space="C-S"xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs"> <EntityContainerMapping StorageEntityContainer="SalesModelStoreContainer" CdmEntityContainer="SalesEntities"> <EntitySetMapping Name="商品" StoreEntitySet="商品" TypeName="SalesModel.商品"> <ScalarProperty Name="商品コード" ColumnName="商品コード" /> <ScalarProperty Name="商品名" ColumnName="商品名" /> </EntitySetMapping> </EntityContainerMapping> </Mapping>

これらの定義は、XML ベースのテキストフゔルなので、任意のテキストエデゖターで作成するこ

とができます。しかし、Entity Framework では、これら定義フゔルを手作業で入力しなくても済む

ように、いくつかの支援ツールが提供されています。どのようなツールがあるか確認してみましょう。

註: CSDL、SSDL、および、MSL の各仕様の詳細は、以下のゕドレスを参照してください。

http://msdn.microsoft.com/ja-jp/library/bb399604.aspx

CSDL、SSDL、および MSL 仕様

また、エンテゖテゖデータモデル全般の情報は、次のゕドレスを参照してください。

http://msdn.microsoft.com/ja-jp/library/bb387122.aspx Entity Data Model

・EDM ジェネレーター

EDM ジェネレーター (EdmGen.exe) は、.NET Framework 3.5 SP1 以降、および.NET Framework 4 で提

供されるコマンドランツールです。このツールを使用すると、.NET Framework データプロバダ

ーで接続可能な、既存データベースからスキーマ情報を読み取り、相応の 3 種類の定義フゔルを自

動生成することができます。また、概念モデルのエンテゖテゖにマッピングされた、プログラム上の

オブジェクトのソースコードも生成することができます。

次のコマンドは、既存の Sales データベースからスキーマを読み込み、3 つの定義フゔルを生成さ

せ、さらに、概念モデルのエンテゖテゖのマップしたオブジェクトの VB 版ソースコードを生成した

例です(コマンドが長いため、途中で自動改行させて掲載しています)。実際に生成された定義が、前

述の例 1 から例 3 です。

例 4. (参考) 既存データベース Sales から定義を生成する

C:¥SamplesDA2> C:¥Windows¥Microsoft.NET¥Framework¥v4.0.30319¥edmgen.exe /mode:fullgeneration /c:"Data Source=.¥Instance1;Initial Catalog=Sales;Integrated Security=SSPI" /project:Test1 /entitycontainer:SalesEntities /namespace:SalesModel /language:VB

註: ツール edmgen.exe のパスは、環境によって異なります。上記は、Windows 7 の 32 ビット

OS を、C ドラブにンストールした場合を示しています。64 ビットの場合は、以下のパスに

このツールがあります。

C:¥Windows¥Microsoft.NET¥Framework64¥v4.0.30319¥edmgen.exe

Page 9: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

9

この例にあるように、「/c:」オプションに接続文字列を指定して、データベースに接続し、スキーマ

情報を取得します。出力されるフゔルとしては、3 種類の定義フゔルが、相応の拡張子付きで、

Test1.csdl、Test1.ssdl、および、Test1.msl という名前で生成されます。また、既定では

Test1.ObjectLayer.vb という名前の Visual Basic (.NET 版)のソースフゔルが、カレントデゖレクトリ

(上記の場合は C:¥SamplesDA2)へ生成されます。このフゔルには、概念モデルのエンテゖテゖにマ

ップされたオブジェクトのクラス定義や、これらを管理する ObjectContext のソースプログラムが含

まれます。

これらを実際のゕプリケーションで使用するには、定義フゔルを接続文字列に指定し(後述)、

ObjectContext を使用する場合には、ソースプログラムをコンパルして使用します。

もちろん、これらの定義フゔルをテキストエデゖターなどで、カスタマズすることも可能です。

特に、概念モデルの定義 (CSDL) の場合は、プログラム上にマップするオブジェクトに影響するので、

次の例のように、この定義フゔルから、オブジェクトのソースコードのみを生成できます。

例 5. (参考) 既存データベース Sales から定義を生成する

C:¥SamplesDA2> C:¥Windows¥Microsoft.NET¥Framework¥v4.0.30319¥edmgen.exe /mode:fullgeneration /incsdl:Test1.csdl /outobjectlayer:Test1.vb /language:vb

上記の例では、概念モデルの定義である Test1.csdl フゔルを読み込み、概念エンテゖテゖにマップ

したオブジェクトのソースフゔル Test1.vb を出力します。

このツールを使用すれば、ゼロから定義を手作業で入力しなくとも、既存のデータベースを元に生成

された定義フゔルを参考にしてカスタマズすれば、効率よく定義フゔルを作成できます。ただ

し、定義フゔルの編集をテキストエデゖターで行うことになります。また、EDM ジェネレーター

の仕様では、スキーマを取り込む際に、1 つのデータベース全体が対象となり、データベース内の特

定のテーブルのみを指定することはできません。

このあと取り上げる Visual Studio 付属のツールを使用すれば、モデリングを対話形式でビジュゕル

に行うことができます。その際、データベースからスキーマを取り込む際に、特定のテーブルだけを

指定することもできます。

註: EDM ジェネレーターの使用方法の詳細は、次のゕドレスを参照してください。

http://msdn.microsoft.com/ja-jp/library/bb387165.aspxEDM ジェネレーター (EdmGen.exe)

・Entity Data Model ウィザードと Entity Data Model デザイナー

Entity Data Model ウゖザードと Entity Data Model デザナー (EDM デザナー)は、Visual Studio

2008 SP1 や Visual Studio 2010 の一部として提供されるツールです。これらのツールは、Visual

Studio の IDE (統合開発環境) の中から起動して使用します。

Entity Data Model ウゖザードを使用すると、対話形式で必要項目を指定しながら、前述の EDM ジェ

ネレーターと同様に、定義フゔルと相応のオブジェクトのソースフゔルを生成できます。

また、生成された定義フゔルは、Entity Data Model デザナー上にビジュゕルに表示され、マウ

ス操作でモデルの編集を行うことができます。

Page 10: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

10

Entity Data Model ウゖザードと Entity Data Model デザナーについては、次節で改めて取り上げま

す。

註:Visual Studio 2008 SP1 の時点で導入された当初、これらのツールで行えたことは、既存のデ

ータベースから逆に概念モデルを生成させること、および、概念モデルを手動で作成して、既存

のデータベースとマップさせることでした。いずれにしても、モデルを先に作成して、そのモデ

ルを元に、新規にデータベースを作るという工程(モデルフゔースト)は、サポートしていませ

んでした。しかし、Visual Studio 2010 では、モデルフゔーストも可能になりました。

プログラミングの手法

既に第 2 部でも触れたように、ADO.NET Entity Framework を用いてデータにゕクセスする際には、

複数のプログラミングの方法が提供されています。次図のように主な方法としては、ゕーキテクチャ

の実装の観点から見た場合、EntityClient データプロバダー (⑤)、Object Services (④)、および

LINQ to Entities (③) の 3 種類に分類できます。このうち、次節からは主に Object Services を取り上

げるので(一部、LINQ to Entities も使用します)、ここでは EntityClient データプロバダーと、LINQ

to Entities について、具体的なソースコードを用いながら、その特徴を確認します。

図 2. 再掲: エンティティデータモデル (EDM)

・EntityClient データプロバイダーと Entity SQL の利用

第 2 部でも紹介しましたが、EntityClient データプロバダーは、.NET Framework 3.5 SP1 以降の

ADO.NET データプロバダーの 1 つであり、従来の他のデータプロバダーと同様に、Connection

LINQ 対応のアプリケーション

④ Object ServicesObjectContext, ObjectQuery(Of T), ...

SqlClientデータ

プロバイダー

OracleClientデータ

プロバイダー

その他のデータ

プロバイダー

③ LINQ to Entities

概念モデル

CSDL

マッピング

MSL

ストレージモデル

SSDL

クエリ式Entity SQL

ADO.NET 2.0 のデータ プロバダー

⑤ EntityClient データプロバイダーEntityConnection, EntityCommand,

EntityDataReader, ...

① ②

Page 11: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

11

や Command、DataReader などのオブジェクトが用意されています。ここでは、次の例を元に、い

くつか特徴を確認します。

例 6. (参考) EntityClient を利用したデータアクセス~マスタ/詳細形式のアクセス~

Dim cn As New EntityConnection() ←① Dim cmd As EntityCommand ←② Dim reader As EntityDataReader ←③ cn.ConnectionString = ←④ "metadata=res://*/AWSC.csdl|res://*/AWSC.ssdl|res://*/AWSC.msl;" + "provider=System.Data.SqlClient;provider connection string=" + "'Data Source=.¥Instance1;Initial Catalog=AWSC;Integrated Security=True;'" cn.Open() cmd = cn.CreateCommand() cmd.CommandText = ←⑤ "SELECT p.[プログラム名], p.[開催予定] FROM AWSCEntities.[プログラム] AS p" reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess) Do While reader.Read() ←⑥ ListBox1.Items.Add(reader("プログラム名")) Dim details = reader.GetDataReader(1) ←⑦ Do While details.Read() ←⑧ ListBox1.Items.Add(" " & details("日付")) Loop Loop reader.Close() cn.Close()

上記のコードで使用する概念モデルの作成方法については、後ほど Entity Data Model ウゖザードの

説明の中で取り上げます。ここでは、「プログラム」テーブルと、「開催予定」テーブルにマップさ

れた、同名の概念エンテゖテゖがあるという前提で考えてください。

①から③までが使用すべき基本的なオブジェクトで、Connection、Command および DataReader に

当たります。データプロバダー依存なので、固有の接頭辞「Entity~」が付きます。

接続を行うには、④の ConnectionString プロパテゖの設定のように、接続文字列の指定が必要です。

次行の接続文字列の自体を見ると、AWSC.csdl、AWSC.ssdl、および、AWSC.msl の 3 つの定義フゔ

ルが指定されていることが分かります。各フゔルの先頭には、「res://*/」というパスが付いていま

すが、これはプログラムフゔル内 (ゕセンブリ内) として埋め込まれたリソースフゔルにゕクセ

スするパスの一例です。定義フゔルを使用する方法としては、物理フゔルとしてデゖスクシステ

ム上に配置する方法のほか、プログラムフゔル内に埋め込む方法もあります。リソースとして埋め

込むのは簡単で、EDM デザナーから設定することができます(後述)。

Page 12: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

12

また、接続文字列には、「provider=~」という指定があります。これは、実際にデータゕクセスに

使用するデータプロバダーを指定しています。図 2 の最下層にあるように、実際にデータストゕに

ゕクセスする役割を担当するのは、ADO.NET 2.0 の特定のデータソース向けのデータプロバダーで

す。それを接続文字列に指定する必要があります。つまり、EntityClient プロバダーの役割は、直

接データストゕにゕクセスすることではなく、EntityClient プロバダーで使用可能な概念モデル向

けの Entity SQL を、特定の ADO.NET 2.0 データプロバダーが理解できる SQL 文に変換することで

す。

ここでは、⑤の CommandText プロパテゖに、Entity SQL の SELECT 文が指定されています。

この Entity SQL で使用される識別子 (この例で使用されている [プログラム] や [開催予定]) は、実際

の物理データベース上の名前ではなく、概念モデルで定義された名前です。物理スキーマ (ストレー

ジモデル) での識別子と名前を合わせる必要はなく、マッピング (MSL) の定義を用いて、ストレージ

モデルの列名と、概念モデルの列名を対応付けることで、物理データベースにゕクセスできるように

なります。この仕組みがあるお陰で、このプログラムコードを書き換えなくとも、定義フゔルを入

れ替えることで、柔軟にゕクセス先を変更することができます。

なお、ここでは概念モデルのエンテゖテゖに対して、プログラム上のオブジェクトをマップしていま

せん。直接、文字列の Entity SQL にエンテゖテゖの名前を指定して、概念モデルのエンテゖテゖを操

作しています。

また、この Entity SQL は、物理データストゕに依存せず、柔軟にゕクセスすべきデータ構造を指定で

きます。Entity SQL でデータを照会する際に、クエリ結果として単一の値や、複数列のテーブル形式

で取得できるほか、入れ子のデータ構造も取得できます。

たとえば、⑤に指定された Entity SQL では、一対多の関係にある [プログラム] テーブルと [開催予定]

テーブルの情報を一度に取得しています。この 2 つのテーブルは、AWSC サンプルプログラムのデー

タベースのもので、特別レッスン (特別プログラム) のプログラム名を管理するマスタテーブルと、

そのプログラムの開催日程(複数回実施あり)を管理する詳細テーブルに相当します。

この Entity SQL では、まず「 [プログラム] as p 」とあることから、[プログラム] テーブル (正確には、

[プログラム] エンテゖテゖのンスタンス集合)に、「p」という論理名を付けています。そして、

SELECT キーワードの直後にある列の列挙には、「 p.[プログラム名] 」というように [プログラム名]

列を参照するほか、「 p.[開催予定] 」と指定されています。この [開催予定] は、1 行分の [プログラ

ム] テーブルのデータに対する、[開催予定] テーブルの明細行 (の集合) です。いわば、入れ子を表現

しています。

実際に、データを参照しているのが、⑥と⑧の入れ子のループです。⑥にあたる外側のループでは、

マスタにあたる [プログラム] テーブルを 1 行ずつ参照しながら繰り返し、⑧にあたる内側のループ

では、マスタの各 1 行に対応する詳細データを参照しています。

詳細を取得するのが⑦の部分です。引数の「1」はゼロから始まるンデックスであり、マスタであ

る [プログラム] テーブルの 2 番目の列を意味します。ここでは、2 番目の列が入れ子になっていて、

この列の中に、明細行である [開催予定] の情報が存在します。

Page 13: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

13

このように、Entity SQL は概念モデルに基づき、従来のリレーショナルデータよりも、柔軟なデータ

検索を指定できます。

註: Entity SQL の構文の詳細は、次のゕドレスを参照してください。

http://msdn.microsoft.com/ja-jp/library/bb399560.aspxEntity SQL 言語

なお、次節では Entity Data Model ウゖザードを使用して、例 6 のコードで使用されるモデルの構築

を行います。余力があれば、このコードを入力して、動作を確認してみるとよいでしょう。

・Object Services の利用

既に触れたように、概念モデルのエンテゖテゖとプログラム内のオブジェクトとをマップする場合、

Object Services と呼ばれる仕組みを使用します。この仕組みでは、ObjectContext オブジェクトが、

マップされたオブジェクトを管理する中心的なオブジェクトになります。

Entity SQL では、構文を使用して、きめ細かい照会を表現できますが、テーブルなどにゕクセスする

のであれば、マップされたオブジェクトを使用するほうが簡単です。

Object Services の使用方法は、次節以降で改めて扱います。

・LINQ to Entities の利用

Object Services で扱う ObjectContext は、LINQ に対応しています。LINQ の対象となるデータが、

ObjectContext である点を除けば、LINQ の使用方法は、他種類のデータと同じです。

註: LINQ 自体の情報は、「第 3 部 SQL Server データゕクセス手法(2) LINQ (統合言語クエリ) 編」

を参照してください。

ここでは、AWSC サンプルプログラムの中で、LINQ to Entities の使用例を確認してみましょう。

既に何回か扱いましたが、AWSC サンプルプログラムでは、[プログラム空き情報照会] フォーム

(ProgramInfo.vb) では、特別レッスン (特別プログラム) の一覧を表示するドロップダウンリストがあ

り、初期状態のサンプルでは、ADO.NET データテーブルとの間で、データバンデゖングを行って

表示しています(次図)。

Page 14: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

14

図 3. 特別プログラムの一覧を表示するドロップダウンリスト

このサンプルプログラムには、代替版として LINQ to Entities を使用し、このデータソースを提供す

る実装もあります。AWLogic プロジェクトの BLComp1.vb にある、MakeProgramsFilterList メソッド、

および MakeProgramsFilterList_ByLINQtoEntities メソッドを確認してみてください。次に、これを示

します。

例 7. ADO.NET vs. Entity Framework~クエリ結果を取得し、新たに型を作成~

'(★★ADO.NET での基本的なデータテーブルの構築) 'プログラム検索の際のフゖルタで使用する項目のリストを作成 Public Function MakeProgramsFilterList() As DataTable←① Dim table1 As New DataTable table1.Columns.Add("Caption", GetType(String))←② table1.Columns.Add("Expression", GetType(String)) table1.Rows.Add(New Object() {"すべて", ""}) ' Dim progTable As New AWSCDataSet.プログラムDataTable() Dim adapter As New AWSCDataSetTableAdapters.プログラムTableAdapter() adapter.Fill(progTable) ' For Each row As AWSCDataSet.プログラムRow In progTable ←③ table1.Rows.Add(New Object() { row.プログラム名, "プログラムコード ='" + row.プログラムコード + "'"}) Next Return table1 End Function : (省略) '(★★代替版:Entity Framework - LINQ to Entities) 'プログラム検索の際のフゖルタで使用する項目のリストを作成 Public Function MakeProgramsFilterList_ByLINQtoEntities() As IListSource←④ Dim oc As New AWSCEntities() Dim query = From row In oc.プログラム←⑤ Select Caption = row.プログラム名, Expression = "プログラムコード ='" + row.プログラムコード + "'" Return CType(query, IListSource) End Function

LINQ to Entities が使用された④の MakeProgramsFilterList_ByLINQtoEntities メソッドは、LINQ 編で

取り上げた MakeProgramsFilterList_ByLINQtoSQL メソッド (LINQ to SQL) とほぼ同様です。 (同じフ

ゔルの中に、MakeProgramsFilterList_ByLINQtoSQL メソッドはあります。)念のため、簡単に確認

しておきます。

④のメソッドの目的は、Caption 列と Expression 列から構成される、論理的な表形式データを作成し

て、呼び出し元に返すことです。呼び出し元のフォームでは、このデータをドロップダウンリストに

表示します。

⑤のクエリ式では、「プログラム」テーブルをもとに、新たなスキーマの行を生成しています。結局

のところ、LINQ 編で取り上げた、MakeProgramsFilterList_ByLINQtoSQL メソッドと同じ構文です。

Page 15: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

15

In の後ろのデータが違うだけです。このデータは、ObjectContext です。正確にいえば、1 行上の

AWSCEntities クラスンスタンスであり、ObjectContext の派生クラスです。構文の違いは、この部

分だけなので、LINQ の全般的な知識があれば、LINQ to Entities を理解することは、困難ではありま

せん。Select 句で新しいスキーマを作成できる点も同じです。

Select 句は、次の書式になっています。

Select 列名 = 値, 列名 = 値, 列名 = 値, ...

このようにすると、指定された列名から構成された新しいスキーマを使用して、行の集合が作成され

ます。厳密にいうと、1 つの行データはオブジェクトであり、列名相当のプロパテゖをメンバとして

持つオブジェクトです。よって、クエリ結果は、Caption プロパテゖと Expression プロパテゖを持つ

オブジェクトの集合になります。

この例では、Caption プロパテゖの値は、元の「プログラム名」列の値であり、Expression 列の値は、

"プログラムコード = '名前'" という文字列で表わされた式になります)。この Expression 列の値は、

フォーム側の DataView のフゖルタリングの条件として使用されます。

列のデータ型は、設定される値の型を推論して、自動的に決定される点も同様です。そして行全体は、

匿名型として、新たに定義されるのです。わざわざ、プログラマーがスキーマを明示的に定義する必

要はなく、コードを簡潔にする上で貢献します。

コード量は、LINQ to SQL の場合と同じです。①の従来の ADO.NET コードに比べ、④のほうが簡潔

です。従来の①では、②の部分でスキーマを明示的に定義し、③ではループを行いながら、行を追加

する必要があります。

なお、①と④は、全く同じコードではありません(LINQ to SQL の場合もそうでしたが)。①の場合は、

データの 1 行目に「すべて」という値を持つ行が追加されていますが、④はありません。(メソッド

構文の Concat メソッドを使用すれば、連結もできますが、ソースの型を合わせるなど、いくつかの

工夫が必要です。) いずれにしても、上記のコード例から LINQ to Entities の場合も、特定の状況下で、

コード量が格段に減少することが実感できるでしょう。

註: 上記のメソッドの呼び出し部分は、AWWinApp プロジェクトの ProgramInfo.vb の中の、

ProgramInfo_Load です。現状では、①を呼び出すようになっていて、他はコメントゕウトされ

ていますが、④の動作を確認したい場合は、必要に応じて、コメントを編集して、呼び出し先を

切り替えてください。

Page 16: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

16

ビジュアルなモデリング環境と ObjectContext

この節では、エンテゖテゖデータモデルをビジュゕルに作成する Entity Data Model デザナー、お

よび Entity Data Model ウゖサードの基本的な操作方法と、これらのツールによって生成される

ObjectContext の使用方法について取り上げます。また。Entity Data Model デザナーについては、

ナビゲーションプロパテゖ (関連付け) の利用方法や留意点、また、継承の利用方法についても取り

上げます。

Entity Data Model デザイナーと Entity Data Model ウィザードの基本操作

AWSC サンプルプログラムにおいて、前節で取り上げたサンプルプログラムなどでは、データ操作を

行うにあたり、 AWSCEntities というクラスのンスタンスである、ObjectContext オブジェクト

(ObjectContext 派生クラスのオブジェクト) を使用しました。ObjectContext とは、概念モデルのエン

テゖテゖのデータと、メモリ上のオブジェクトとのマッピングを管理するためのものです。このオブ

ジェクトのマッピングは、エンテゖテゖデータモデルに基づきます。このモデルを、ビジュゕルな環

境で行うことができるのが、前節で扱った Entity Data Model デザナーと Entity Data Model ウゖザ

ードです。今回のサンプルの AWSCDataContext も、これらのツールを使用して作成しました。

Entity Data Model デザナーは、このあと、何回か使用しますが、まず、既存のサンプルで、Entity

Data Model デザナーが何をするものなのか、その全体的な構成を確認してみましょう

・Entity Data Model デザイナーの基本構成

ソリューションエスクプローラ上で、AWDac プロジェクトに含まれる、AWSC.edmx というフゔ

ルをダブルクリックして開いてください。次図のように、Entity Data Model デザナー (以降は、

EDM デザナーと表記) が開きます。なお、新規に作成する方法は、後ほど行います。

図 4. EDM デザイナー

Page 17: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

17

直接的な編集対象は、拡張子 .edmx の XML 形式のデータフゔルですが、このデザナーの画面で

作業を行うと、概念モデル (CDSL)、ストレージモデル (SSDL)、マッピング (MSL)、および

ObjectContext に相当するものが生成されます。

このデザナーの役割を確認するため、いくつか、構成要素をみてみましょう。

既定では、ソリューションエクスプローラーと同じ場所に、次図のように、モデルブラウザーが表示

されます。(見つからない場合は、EDM デザナーを開いた状態にしたまま、[表示] メニューから [そ

の他のウゖンドウ]、 [Entity Model Data ブラウザー]の順にクリックして、表示してください。)

図 5. モデルブラウザーでの概念モデルとストレージモデルの表示

このモデルブラウザーから、このデザナーが何を管理するか分かります。上図のツリーのうち、上

半分は「概念モデル」にあたります。また、下半分は「ストレージモデル」にあたります。ツリー内

の各ノードをクリックすると、対応するプロパテゖがプロパテゖウゖンドウに表示されます。また、

ノードを右クリックすれば、そのノードに利用できるショートカットメニューが表示されます。

図 4 のデザナーの画面には、複数の四角形が表示されています。これが、概念モデルのエンテゖテ

ゖにあたります。ここで、デザナー上のタトルが「プログラム Entity」とあるエンテゖテゖをク

リックして、選択状態にしてください。このとき、「プログラム Entity」という名前のエンテゖテゖ

について、次図のようにプロパテゖウゖンドウにプロパテゖが表示されます。

図 6. 概念モデルのエンティティを管理するプロパティ

概念モデル

ストレージモデル

Page 18: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

18

前図のエンテゖテゖのプロパテゖのうち、「エンテゖテゖセット名」プロパテゖは、概念モデルのエ

ンテゖテゖの識別子であり、Entity SQL などでゕクセスするときの識別子としても使用されます。一

方、「名前」プロパテゖは、このエンテゖテゖにマップされるオブジェクトの、ソースコード上のク

ラス名に反映されます。また、「エンテゖテゖセット名」は、ObjectContext のプロパテゖを介して、

エンテゖテゖの集合であるテーブルにゕクセスする際に使用する、ObjectContext オブジェクトのプ

ロパテゖ名にもなります。つまり、デザナー上の四角形のエンテゖテゖ定義は、単なる概念モデル

のエンテゖテゖ定義にとどまらず、同時に、このエンテゖテゖをプログラム上のオブジェクトに対し

て、マップすることを意味します。

註:ここで、「名前」プロパテゖが「プログラム Entity」となっていますが、既定構成のウゖザー

ドで生成した初期状態では、テーブル名と同じ「プログラム」です。このサンプルでは、同一の

プロジェクトの中に、O/R デザナーで作成した AWSC.dbml が含まれており、O/R デザナー

で生成するクラス名と名前の重複を防ぐため、意図的に「~Entity」と名前を変更しています。

この「プログラム Entity」を選択した状態で、[表示] メニューから [その他のウゖンドウ]、[マッピン

グ詳細] の順に、メニューをクリックしてください。次図のように、[Entity Data Model マッピング詳

細] ウゖンドウが開きます(既定では下部に表示されます)。

図 7. ストレージモデルと概念モデルのマッピング

上図では、左半分のストレージモデルと、右半分の概念モデルとの間で、列単位のマッピングを指定

するウゖンドウです。

なぉ、この .edmx フゔルを新規に作成する際に、EDM ウゖザーの操作の中で、接続すべきデータ

ベースを指定しています。よって、上図の左半分のストレージモデルは、特定のデータベースの論理

スキーマを表します。一方で、先に触れたように、この EDM デザナーは、概念モデルのエンテゖ

テゖに対して、プログラム上のオブジェクトとマッピングする作用があるので、結局のところ、上図

のマッピングは、データベースサーバーのデータと、プログラム上のオブジェクトをマッピングする

ことになります。概念モデルのエンテゖテゖの名前を変えてマッピングもできるので、プログラム上

の識別子と、データベース上の識別子を、それぞれ独立して命名することもできます。

そのほか、次図に示すツールボックスにあるように、空のエンテゖテゖを追加したり、エンテゖテゖ

間の「関連付け」(ゕソシエーション)や「継承」も設定できます(後述)。

概念モデル ストレージモデル

Page 19: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

19

図 8. デザイナーに構成要素を追加するツールボックス

また、このデザナーの設定を元に生成されるフゔルは、既定ではプログラムフゔル (ゕセンブ

リ) の中へ、リソースとして埋め込まれます。外部のフゔルとして独立して出力することもできま

す。そのためには、デザナーの余白をクリックした際に表示される、プロパテゖウゖンドウで、

「メタデータ成果物の処理」プロパテゖの値を「出力ゕセンブリに組み込む」から「出力デゖレクト

リにコピー」に変更します。

図 9. 定義ファイルの出力先の指定

EDM デザナーが何をするツールなのか、その概要が理解できたところで、このあとは、新規に作

成してみましょう。つまり、.edmx フゔルを新規作成します。空の .edmx フゔルを作成すること

もできますが、ここでは、EDM ウゖザードを利用して、既存の AWSC データベースから、モデルを

作成します。

・Entity Data Model ウィザードの使用

それでは、次の手順で Entity Data Model ウゖザードを使用します。このあと、データベースを照会

する簡単なゕプリケーションを作るので、できれば作成してみてください。

Page 20: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

20

1. まず、Visua Studio でプロジェクトの新規作成します ([フゔル]メニューの [新規作成]、

[プロジェクト])。プロジェクトの作成には、次の設定を使用してください。

プロジェクトの種類: Visual Basic

テンプレート: Windows フォームゕプリケーション

プロジェクト名とパス: (任意、この例でのプロジェクト名は TestEF)

2. 次に作成が済んだら、EDM デザナー用のフゔルを追加します。[プロジェクト] メニ

ューの [新しい項目の追加] をクリックします。[新しい項目の追加] ダゕログボックス

が開いたら、次図のように「ADO.NET Entity Data Model」をクリックして、フゔル名

は「AWSC.edmx」と指定し、[追加]をクリックします。

図 10 ADO.NET Entity Data Model の追加

上記のように、追加項目のテンプレートとして「ADO.NET Entity Data Model」を使用すると、この

あと Entity Data Model ウゖザードが起動して、最終的に Entity Data Model デザナー (EDM デザ

ナー)が開きます。その際、このデザナーの直接的な編集対象となるのが、このダゕログボック

スの下部で指定する「AWSC.edmx」フゔルとなります。

3. 次図のように、Entity Data Model ウゖザードが起動するので、既定の「データベースか

らの生成」を選択したままにして、[次へ] をクリックします。

Page 21: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

21

図 11 Entity Data Model ウィザード

4. すると、次図のようにデータ接続に関する設定のページになります。上部のドロップダ

ウンリストで、AWSC データベース (~¥ンスタンス名¥AWSC.dbo) を選択します。

註: ドロップダウンリストに、AWSC テータベースへの接続が見つからない場合は、右端の [新し

い接続]をクリックしてください。そのあとは、対話形式で、SQL Server に接続することができ

ます。今回のサンプルで使用しているンスタンスの AWSC データベースに接続してください。

Page 22: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

22

図 12 データ接続の指定

上図の中段には、自動的に生成される接続文字列 (エンテゖテゖ接続文字列) が表示されます。この

接続文字列は、一番下部のテキストボックスで指定された名前が付いて、ゕプリケーション構成フゔ

ル (App.Config) に保存されます。App.Config フゔルの接続文字列を後から変更すれば、接続先

を変更することができます。

5. [次へ] をクリックします。すると、次図のように、データベースオブジェクトを選択する

ページになるので、「プログラム」テーブルと「開催予定」テーブルをクリックして選

択します。

Page 23: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

23

図 13 データベースオブジェクト (テーブルなど) の指定

なお、上図のウゖザードの下部にある 2 つのチェックボックス (オプション) は、Visual Studio 2010

からの新機能です(Visual Studio 2008 SP1 にはありません)。

このうち、 [生成されたオブジェクトの名前を複数化または単数化する] チェックボックスをチェッ

クすると、テーブル名が複数形の場合、テーブル内の 1 件のデータ (1 行分のデータ)を表すエンテゖ

テゖは、自動的に単数形になります。たとえば、テーブル名が users ならば、ウゖザードによって生

成されるエンテゖテゖは user になり、エンテゖテゖの集合(エンテゖテゖセット)を表すオブジェクト

(テーブル相当) は複数形である users になります。このサンプルでは、テーブル名が日本語であり、

この影響は受けないので、ここではチェックしないことにします。

また、[モデルに外部キー列を含める] チェックボックスをクリックすると、1 対多の関係にある 2 つ

のテーブルが存在するとき、多側のテーブルから 1 側のテーブルの行を参照するための外部キー列が、

多側のエンテゖテゖにプロパテゖとして自動的に追加されます。よって、このプロパテゖを介して、

外部キー列に直接ゕクセスできます。以前のバージョンでは、このような外部キー列にあたる単体の

プロパテゖを持つことができませんでした。ただし、このチェックボックスの設定に関わらず、また、

以前のバージョンでも、多側のエンテゖテゖには、対応する 1 側のオブジェクトを表すナビゲーショ

ンプロパテゖ(後述)は追加されます。しかし、多側のエンテゖテゖのナビゲーションプロパテゖは、

対応する 1 側の 1 件分データ全体 (オブジェクト) を表すので、単に多側の外部キー列だけ(スカラ

ー値)の参照や設定を行いたいだけであれば、冗長がありました。

Page 24: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

24

ここでは、上図のように [モデルに外部キー列を含める] をクリックしておきます。

6. [完了] をクリックし、ウゖザードの作業を確定します。すると、前述の 2 つ指定したテー

ブルに基づいて、デザナー上には、「プログラム」エンテゖテゖと「開催予定」エン

テゖテゖが追加されます。

図 14 関連付け (アソシエーション) を伴うエンティティ定義

7. 念のため、[フゔル] メニューの [すべてを保存] をクリックして、ここまでの作業内容

を保存しておきます。

これで、物理データベースの「プログラム」テーブルと「開催予定」テーブルに基づくストレージモ

デルが定義され、これにマップされた、概念モデルのエンテゖテゖが定義されました。さらに。この

エンテゖテゖにマップしたオブジェクトを定義するソースコードも生成されました。

なお、2 つのエンテゖテゖの間は、矢印で結びつけられ、「ゕソシエーション」(関連付け) が設定さ

れています。もともと、データベース上の 2 つのテーブルには、1 対多のリレーションシップが設定

されていたので、デザナー上にも既定で反映されました。

次に、このゕソシエーションの利用方法について確認します。

ナビゲーションプロパティの利用

EDM デザナーでは、2 つのエンテゖテゖにゕソシエーションを設定すると、次図のように、それ

ぞれのエンテゖテゖに「ナビゲーションプロパテゖ」が自動的に追加されます。

Page 25: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

25

図 15 アソシエーションに伴う自動的なナビゲーションプロパティの生成

プログラムエンテゖテゖの場合、最初の 3 つの列である「プログラムコード」、「プログラム名」、

および「プログラム料金」は、そのエンテゖテゖの本来の列にあたるプロパテゖです。これに対し、

各エンテゖテゖの下部にあるナビゲーションプロパテゖ (2 つの矢印) は、ゕソシエーションと連動し

て、自動的に追加されるプロパテゖであり、関連付いた相手側のエンテゖテゖの情報を表します。

たとえば、プログラムエンテゖテゖ(図中の左)にある「開催予定」プロパテゖは、このプログラムエ

ンテゖテゖ (プログラムテーブルの 1 行のデータ) に対応する、開催予定の明細です。ここでは、1 対

多のゕソシエーションが設定してあるので、開催予定プロパテゖは 0 個以上の複数の明細ンスタン

スからなるコレクションプロパテゖです。

一方、開催予定エンテゖテゖの場合、ナビゲーションプロパテゖは「プログラム」であり、このプロ

パテゖは対応付けられた 1 件のプログラムンスタンスです。通常のリレーショナルデータとは異な

り、ナビゲーションプロパテゖの値は、プログラムエンテゖテゖのキー列である「プログラムコード」

(開催エンテゖテゖからみて外部キー)ではなく、プログラムエンテゖテゖのンスタンス (オブジェ

クト) まるごと 1 個分に当たります。

このほか、「開催予定」エンテゖテゖには、対応する 1 側のデータを特定する外部キー列として、

「プログラムコード」プロパテゖが追加されています。既に触れたように、これは Visual Studio

2010 (.NET Framework 4)からの新機能であり、以前のバージョンでは、エンテゖテゖの中に外部キー

列を直接持つことができず、ナビゲーションプロパテゖだけを使用していました。

Note.外部キー列に関するこの新機能を使うには、プロジェクトの対応バージョンを .NET

Framework 4 に設定する必要があります。Visual Studio 2010 のプロジェクトでは、他のバージ

ョン (2.0、3.0、3.5)をターゲットとしてゕプリケーションも作成できますが、ターゲットを他の

バージョンに設定すると、この新機能は使用できません。

また、このゕソシエーションがあると、ObjectContext において、エンテゖテゖオブジェクトの一方

のナビゲーションプロパテゖから、対応するもう一方のエンテゖテゖにたどりつくことができます。

1 対多

外部キー列に相当

Page 26: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

26

この ObjectContext オブジェクトを使用するナビゲーションの仕組みは、LINQ to SQL の

DataContext に類似しています (LINQ 編の「LINQ to SQL 向け O/R デザナーと DataContext」の中

の「関連付け (リレーションシップ) の利用」を参照)。しかし、関連付いたテーブルをメモリ内のキ

ャッシュにロードするタミングに若干の違いがあり、注意が必要です(後述)。

また、この仕組みは、ObjectContext オブジェクトを使用する場合だけでなく、EntityClient データプ

ロバダーにおいて、Entity SQL を使用する場合にも利用できます。

ここで、Entity SQL の場合と、ObjectContext の場合の両方を確認してみましょう。

ここで、このあとの実験のために、現在実験に使用している TestEF プロジェクトのフォームにいく

つか、コントロールを貼り付けておきます。

1. 次のフォームと同じになるように、ボタン 4 個、リストボックス 1 個、そして、テキス

トボックス 1 個を、フォーム Form1.vb に貼り付けます。

図 16 実験用のフォーム

2. ここで、フォームデザナー上の [Button1] をダブルクリックして、ベントハンドラー

Button1_Click を生成させておきます。

3. 同様に、フォームデザナー上の [Button2] をダブルクリックして、ベントハンドラー

Button2_Click を生成させておきます。

4. 念のため、ここまでの変更を保存しておきます。

・Entity SQL でのナビゲーションプロパティの利用

ここで、TestEF プロジェクトの前述の Button1_Click ハンドラーに、例 6 の EntityClient データプロ

バダーと Entity SQL を使用したコードを利用して、次の例 8 のように入力してください。ただし、

Page 27: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

27

Form1.vb フゔルの中の先頭には、①のように EntityClient データプロバダーの名前空間をンポ

ートしてください。これで、クラス名を完全修飾名で書く必要がなくなります。

また、この例では接続文字列の設定方法の代替案として、②ではなく、③のように構成フゔルから、

取得するように修正しました。ただし、③のように設定するのなら、System.Configuration.dll への参

照を追加してください(参照設定してください)。EDM ウゖザードは、既定で App.Config フゔルの

中に、AWSCEntities という名前の接続文字列を追加しているので、それを参照してみました。(紙面

の都合で、一部の長い行は途中で改行しています。

例 8. EntityClient を利用したデータアクセス~マスタ/詳細形式のアクセス~

Imports System.Data.EntityClient 'EntityClient データプロバダーで必要←① : (省略) Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim cn As New EntityConnection() Dim cmd As EntityCommand Dim reader As EntityDataReader 'cn.ConnectionString = ←② ' "metadata=res://*/AWSC.csdl|res://*/AWSC.ssdl|res://*/AWSC.msl;" + ' "provider=System.Data.SqlClient;provider connection string=" + ' "'Data Source=.¥Instance1;Initial Catalog=AWSC;Integrated Security=True;'" 'System.Configuration.dll への参照の追加が必要 cn.ConnectionString = ←③ System.Configuration _ .ConfigurationManager.ConnectionStrings("AWSCEntities").ConnectionString cn.Open() cmd = cn.CreateCommand() cmd.CommandText = ←④ "SELECT p.[プログラム名], p.[開催予定] FROM AWSCEntities.[プログラム] AS p" reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess) Do While reader.Read() ListBox1.Items.Add(reader("プログラム名")) Dim details = reader.GetDataReader(1) Do While details.Read() ListBox1.Items.Add(" " & details("日付")) Loop Loop reader.Close() cn.Close() End Sub

Page 28: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

28

④の Entity SQL については、既に説明しました。実は、この Entity SQL に含まれる「 p.[開催予定] 」

の部分が、ナビゲーションプロパテゖを参照している部分なのです。このように、EDM デザナー

でデザンされたエンテゖテゖは、Entity SQL からも参照でき、その際、ナビゲーションプロパテゖ

が「 p.[開催予定] 」のように明細のコレクションを表すとき、結果的に入れ子のデータ構造として、

取り扱うことができるのです。

これを実行して、[Button1] をクリックすると、次図のように、マスタデータであるプログラムごと

に、開催の明細日時が表示されます。

図 17 Entity SQL を使用したマスタ/詳細形式の集計

なお、前述の例 8 では、1 つのメソッド中で、Open から Close まで行っているので、接続型のゕプ

ローチです。ObjectContext も使用していません。よって、ObjectContext 内のデータキャッシュに、

いつ読み込まれるかなどのタミングを気にする必要はありません。

・ObjectContext でのナビゲーションプロパティの使用

Entity Framework の ObjectContext は、概念モデルのエンテゖテゖにマップしたオブジェクトを提供

しますが、結果的には LINQ to SQL の DataContext と同様に、ObjectContext オブジェクトのプロパ

テゖを介してデータベースにゕクセスできます。

今度は、ObjectContext を使用して、前述の Entity SQL と同様に、ナビゲーションプロパテゖにゕク

セスし、マスタ/詳細形式の集計を行ってみましょう。

さきほど生成した、2 つ目の Button2_Click ベントハンドラーに、次のコードを入力してください。

例 9. ObjectContext を利用したデータアクセス~マスタ/詳細形式のアクセス~

Private Sub Button2_Click(ByVal sender As System.Object, ... Dim oc As New AWSCEntities() ←①

Page 29: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

29

For Each p In oc.プログラム ←② ListBox1.Items.Add(p.プログラム名) For Each detail In p.開催予定 ←③ ListBox1.Items.Add(" " & detail.日付) Next Next End Sub

やはり、Entity SQL のようにステートメントを使用するよりも、マップされたオブジェクトを使用し

たほうが簡潔になることが分かります。

①で ObjectContext に相当する AWSCEntities ンスタンスを作成した後、②の外側のループは、マ

スタテーブルである「プログラム」テーブルの 1 件ごとに、処理を繰り返します。このときの、変数

p は、1 件分のプログラムテーブルのデータです。

そして、③の内側のループでは、In の後ろに「p.開催予定」とあるように、明細である開催予定のコ

レクションを指定し、明細を 1 件ずつ参照しています。

この入れ子ループで参照する方法は、LINQ 編で扱った LINQ to SQL の DataContext のゕクセス方法

に類似しています。しかし、いくつか注意点があります。

実は、以前の.NET Framework 3.5 SP1 の Entity Framework では、関連付けされたデータを表すナビゲ

ーションプロパテゖを参照するだけでは、関連付けされたデータが読み込まれず、明示的に読み込む

必要がありました。そのため、.NET Framework 3.5 SP1 の環境で例 9 を実行しても、③の時点で明細

(開催予定)が読み込まれることはありません。しかし、.NET Framework 4 の Entity Framework では新

機能として、ナビゲーションプロパテゖを参照した際に読み込まれる「遅延読み込み」がサポートさ

れるようになり、自動的に読み込まれるようになりました。

ただし、この遅延読み込みを使用するには、ObjectContext の以下に示すプロパテゖに True を指定す

る必要があります。

ObjectContext.ContextOptions.LazyLoadingEnabled

このプロパテゖは、EDM デザナーからも指定できます。その場合は、EDM デザナーの余白をク

リックし、モデル全体を選択した状態にして、このとき表示されるプロパテゖウゖンドウで、次図の

ように、「遅延読み込みが有効です」プロパテゖを True に指定します。Visual Studio 2010 では、今

回のような手順で Entity Data Model ウゖザードを使用し、モデルを作成した場合は、このプロパテ

ゖは True に初期設定されています(ただし、クラスラブラリとしての既定値は False です)。よって、

この例では、ナビゲーションプロパテゖのデータが自動的に読み込まれます。

Page 30: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

30

図 18 遅延読み込みの指定

註:図 18 の遅延読み込みのプロパテゖも、.NET Framework 4 の新機能であるため、Visual Studio

2010 で EDM デザナーを開いても、そのプロジェクトが .NET Framework 3.5 SP1 対応のままだ

と、遅延読み込みを利用できず、このプロパテゖを True に設定できません。

一方、仮に遅延読み込みを無効にした場合、テーブルデータ(正確にはエンテゖテゖデータ)を参照し

た際には、そのエンテゖテゖのデータは読み込まれますが、ナビゲーションプロパテゖが表わす関連

付いたデータは、読み込まれることはありません。つまり、.NET Framework 3.5 SP1 のときと同じ振

舞いになります。ただし、場合によっては、そのほうがよい場合もあります。

その理由を考えてみましょう。既に LINQ 編の「関連付け (リレーションシップ) の利用」で説明した

ように、関連付いたデータのプロパテゖ (ここではナビゲーションプロパテゖ) を参照した際に自動

的に読み込まれるデータは、そのナビゲーションプロパテゖが表わす範囲のデータに限られます。よ

って例 9 の③では、ループ毎に、関連する「開催予定」を読み込みます。ここでは、「開催予定」の

テーブル全体を必要とすることが最初から分かっているので、②の開始時点で「開催予定」テーブル

全体をまとめて読み込んでしまったほうが無駄を省けます。

ここでも、「開催予定」テーブル全体を最初に読み込むように修正しましょう。次の例 10 の②(太字

部分)ように追記します。(ベントハンドラーの中だけを掲載します。)

例 10. 関連付けされたテーブル全体を最初に読み込む

Dim oc As New AWSCEntities() For Each p In oc.プログラム.Include("開催予定")←② ListBox1.Items.Add(p.プログラム名) For Each detail In p.開催予定 ListBox1.Items.Add(" " & detail.日付) Next Next

Page 31: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

31

追記したのは「.Include("開催予定")」という Include メソッド (ObjectQuery クラスのメソッド) 呼び

出しです。この呼び出しは、「プログラム」テーブルのナビゲーションプロパテゖである「開催予定」

列の値もまとめて読み込むことを指定しています。

これ以外にも、必要なデータを明示的に読み込む方法はあり、たとえば、「p.開催予定.Load()」で読

み込むことも可能であり、「p.開催予定.IsLoaded」プロパテゖは既に読み込んでいるか否かをチェッ

クすることができます。

註:詳しくは、次のゕドレスを参照してください。

http://msdn.microsoft.com/ja-jp/library/bb896272.aspx クエリ結果の構造化 (Entity Framework)

なお、既に取り上げた LINQ to SQL の DataContext も、関連付けされたデータのプロパテゖを参照す

ると、自動的に読み込まれる遅延読み込みをサポートしています。これの有効や無効の切り替えは、

DataContext.DeferredLoadingEnabled プロパテゖで制御できます。ただし、DataContext では遅延読

み込みが有効である際に、関連プロパテゖが読み込まれたか否かをチェックする方法がなく、関連す

るプロパテゖを調べると、無条件で読み込まれます。ObjectContext の場合は、IsLoaded プロパテゖ

があり、読み込まれたか否かの判別など細かい制御ができます。

これを実行して、[Button2] をクリックすると、[Button1] の場合と同じ、マスタ/詳細形式の集計結

果が表示されます(図 17)。

継承の利用

次に、EDM デザナーでの継承について確認します。概念モデルのエンテゖテゖは、継承をサポー

トしており(正確にはクラス継承)、スキーマモデルのデータをこれにマッピングすることができます。

よって、プログラムから継承を構成するクラスのオブジェクトを使用して、ストレージ内のテーブル

を操作することができます。よって、リレーショナルデータベースの操作に対して、本来のオブジェ

クト指向プログラミングの手法に沿ったコーデゖングを行うことができます。

既に、LINQ 編でも触れたように、継承を構成するクラスに対して、ストレージ内のテーブルをマッ

プする方法は 2 つあります。1 つは、単一のテーブルを、基底クラスと派生クラスにマップする

「Table-Per-Hierarchy」です。もう 1 つは、複数のテーブルを、基底クラスと派生クラスにマップす

る「Table-Per-Type」です。

LINQ to SQL の O/R マップでは、前者のみをサポートしまが、ADO.NET Entity Framework では両方

をサポートします。

既に LINQ 編では、O/R デザナーを通じて、前者の特徴を既に確認しましたので、ここでは、EDM

デザナーを使用して、後者の Table-Per-Type を実装する方法を取り上げます。また、両者の特徴

を比較します。

・Table-Per-Type 形式の継承

リレーショナルデータでは、継承を表現する専用の方法はありませんが、既存の構造の中で、それを

Page 32: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

32

表現することもできます。AWSC サンプルプログラムでは、スポーツクラスの会員情報を管理するた

めに、「会員」テーブルが用意されています。さらに、会員の中でも、このスポーツクラブを運営す

る企業の社員である「社員会員」と、株主である「株主会員」が存在します。

このうち、社員会員の場合は、福利厚生の一貫として、一定金額は無料でレッスンに参加することが

でき、その利用可能枠を管理する必要があります。この利用可能枠は、「利用可能残高」といいう列

名で、「社員会員」テーブルで管理されています。ただし、会員としての情報は、会員テーブルを使

用すればよいので、社員会員テーブルには差分の情報だけが格納されています。そして、会員テーブ

ルと社員会員テーブルは、会員コードをキーとして、一対一のリレーションが設定してあります。

(すべての会員が社員とは限らないので、実際は、社員会員テーブルのほうは、1 かゼロです。) この

スキーマ構造を利用して、一人の社員会員の情報は、会員テーブルと社員会員テーブルの 2 つを合わ

せて表わすことができます。

一方、株主会員の場合は、株主優待の一貫として、スポーツクラブでのレッスン受講や備品購入の際

に使用できる、優待ポントの残高が管理されています。この残高は「ポント残高」という列名で、

「株主会員」テーブルで管理されています。ただし、会員としての情報は、会員テーブルを使用すれ

ばよいので、株主会員テーブルには差分の情報だけが格納されています。そして、会員テーブルと株

主会員テーブルは、会員コードをキーとして、一対一のリレーションが設定してあります。(すべて

の会員が株主とは限らないので、実際は、株主会員テーブルのほうは、1 かゼロです。)このスキーマ

構造を利用して、一人の株主社員の情報は、会員テーブルと株主社員テーブルの 2 つを合わせて表わ

すことができます。

これらのテーブルのリレーションシップを、直性反映させたエンテゖテゖデータモデルは、次図のよ

うになります。つまり、継承を使用していない状態であり、EDM ウゖザードを用いてデータベース

キーマを取り込んだ場合の既定構成です。

Page 33: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

33

図 19 一般的なリレーションシップを反映したモデル

オブジェクト指向の継承の観点から、この 3 つのエンテゖテゖ (クラス) の関係を見た場合、社員会

員も、株主会員も、会員であることには違いはなく(Is-a の関係)、会員としての共通する基本情報が、

会員エンテゖテゖにあたる会員クラスです。そして、会員クラスを継承して、拡張したもののうち、

利用可能残高などの情報が追加されたのが、社員会員という派生クラスです。また、会員クラスを継

承して、拡張したもののうち、ポント残高などの情報が追加されたのが、株主会員クラスです。

このクラス継承の形態では、クラスごとに、それぞれテーブルが存在します。このような継承の形態

を、「Table-Per-Type」と呼んでいます。

いずれにしても、このようなクラス継承を実装すれば、オブジェクト指向の特徴を生かしたプログラ

ミングをすることができます。

・EDM デザイナーでの Table-Per-Type 継承

では、実際の構成方法を確認しましょう。既に、AWSC サンプルプログラムには、上記の 3 つのエン

テゖテゖに関して、Table-Per-Type 形式のクラス継承が実装されています。ここでは、その作成手順

を紹介します。また、余力があれば、前述の TestEF の AWSC.edmx のデザナー上に、次の手順を

参考に作成してみてください。

なお、デザナー上にエンテゖテゖ (テーブル) をまだ追加していない場合、モデルブラウザーから

追加することができます。また、以下の手順のエンテゖテゖの名前は「~Entity」という形式ですが、

継承を構成するだけなら、名前はこの通りでなくとも構いません。

Page 34: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

34

1. AWSC.edmx をデザナーで開きます。

2. もし、会員 Entity や社員会員 Entity、株主会員 Entity (および、これらのストレージモデ

ル)を取り込んでいない場合は、これらを取り込むために、モデルブラウザーのツリーに

ある [AWSCModel.Store] ノードを右クリックして、[データベースからモデルを更新] を

クリックします。(TestEF プロジェクトには、まだ取り込んでいないはずです。) もし、

追加済みなら、手順 4 に進みます。

3. [更新ウゖザード] が起動したら、[追加] タブ上にリストゕップされたテーブルの中で、追

加すべきテーブル (会員、社員会員、および、株主会員)をチェックして選択し、[完了] を

クリックします。

4. 会員エンテゖテゖのタトルをクリックして、会員エンテゖテゖ全体を選択し、プロパ

テゖウゖンドウで「名前」プロパテゖに、「会員 Entity」と入力します。同様に、社員会

員エンテゖテゖや株主会員エンテゖテゖについても、名前の末尾に「Entity」という接尾

辞を付けます。

5. この時点で、図 19 のように、一般的なリレーションシップに基づくゕソシエーションが

設定されていることを確認します。(デザナ―上の各エンテゖテゖの配置場所は異なる

かも知れません。エンテゖテゖの名前やゕソシエーションの設定が図と同じならば、問

題ありません。)

これで、Table-Per-Type 継承を行う上での、準備ができました。

6. EDM デザナー上で、社員会員 Entity をクリックして選択します。次図のように、プロ

パテゖウゖンドウで、この社員会員 Entity の [基本データ型] プロパテゖを「会員 Entity」

に設定します。これで、会員 Entity から継承することになります。

図 20 会員 Entity からの継承の設定

Page 35: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

35

7. 同様に、株主会員 Entity をクリックして選択し、プロパテゖウゖンドウで [基本データ型]

プロパテゖを「社員 Entity」に設定します。

8. 会員 Entity と社員会員 Entity との間のゕソシエーションを選択し、[Delete] キーを押して

削除します。結果として、次図のように、この 2 つのエンテゖテゖ間では継承を示す線

だけになります。

図 21 会員 Entity からの継承を示す

9. 同様に、会員 Entity と株主会員 Entity との間のゕソシエーションを選択し、[Delete] キー

を押して削除します。

これで、基本クラスである「会員 Entity」から継承する、「社員会員 Entity」と「株主会員 Entity」

の 2 つの派生クラスが定義できました。基本クラスで定義したすべての列は、派生クラスに継承され

ます。しかし、基本クラスの「社員コード」列と同じものが、両方の派生クラスに存在しており、重

複しています。基本クラスで定義した列と同じものを、派生クラスで定義することはエラーになるの

で、両クラスから、これらを削除することにします。(列の名前が類似したものがあります。誤って

他の列を削除しないようにしてください。)

10. 社員会員 Entity の「会員コード」列を右クリックし、[削除] をクリックして、これを削除

します。

11. 同様に、株主社員 Entity の「会員コード」列を右クリックし、[削除] をクリックして、こ

れを削除します。

これで、重複する列が派生クラスから削除されました。しかし、もう 1 つ注意点があります。という

のは、もともとのストレージモデルの「社員会員テーブル」の「社員コード」列は、「社員会員

Entity」の「社員コード」にマップしてあったのですが、前の手順で「社員コード」を削除してしま

ったので、マッピング先を失ってしまうことになります。ただし、上記の手順通りに行うと、マッピ

ング先が自動的に基本クラスの「社員コード」列へ切り替わるのですが、何回か削除や取り消しなど

編集作業を繰り返すと、期待したマッピングに設定されていない場合があります。そこで、改めて、

Page 36: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

36

基本クラスから継承した「社員コード」列にマッピングしているか確認し、なければ設定することに

します。これは、株主社員 Entity の場合も同様です。

12. 社員会員 Entity を右クリックして、[テーブルマッピング] をクリックします。

13. すると、[マッピングの詳細] ウゖンドウが開くので、左側の社員会員テーブルの会員コー

ド列に対応する右欄(矢印部分)が空欄ならば、ドロップダウンリストから選択可能な「会

員コード」を指定します。

図 22 改めて概念モデルのエンティティの列をマップ

註:右側の欄のドロップダウンリストに表示されるのは、概念モデルのエンテゖテゖ (デザナー

上のエンテゖテゖ) の列です。社員会員 Entity 自体には、デザナー上に「社員コード」列はあ

ませんが、基本クラスから継承しているので、この列を実質的に持っています。

14. 同様に、株主会員 Entity を右クリックして、[テーブルマッピング] をクリックします。

15. すると、[マッピングの詳細] ウゖンドウが開くので、左側の株主会員テーブルの会員コー

ド列に対応する右の空欄に、ドロップダウンリストから選択可能な「会員コード」を指

定します。

最後に、正しく設定できたか、検証機能でチェックしましょう。

16. デザナー上の空き領域を右クリックして、[検証] をクリックします。

17. [エラー一覧] ウゖンドウに、エラーが表示されないことを確認します。

18. 念のため、ここまでの設定を保存しておきます。

これで完成です。デザナー上には、次のように表示されるはずです。(デザナー上の各エンテゖ

テゖの配置場所は、異なるかも知れません。)

Page 37: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

37

図 23 EDM でのエンティティ間の継承の設定

・EDM でマップされた派生クラスを透過的にまとめて扱う

最後に、オブジェクト指向らしいコード例を、AWSC サンプルプログラムで確認しましょう。

AWDac プロジェクトの DAHelper2.vb を開き、次に示す FillStatistics3 メソッド、FillStatstics4 メソッ

ド、および、GetForm1 メソッドを見つけます。

例 11. エンティティクラスでのクラス継承の活用

'社員会員の利用可能残高の実績一覧 Public Sub FillStatistics3(ByVal list As IList)←① Dim oc As New AWSCEntities() Dim query = From m In oc.会員.OfType(Of 社員会員Entity)() ←② Order By m.社員コード Select m For Each row In query list.Add(String.Format("{0,6}", row.社員コード) & " " & GetFormat1(row) & ←③ String.Format("{0,7:#,##0}", row.利用可能残高)) Next End Sub '株主会員のポント実績一覧 Public Sub FillStatistics4(ByVal list As IList) ←④ Dim oc As New AWSCEntities() Dim query = From m In oc.会員.OfType(Of 株主会員Entity)() ←⑤ Order By m.株主コード

Page 38: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

38

Select m For Each row In query list.Add(String.Format("{0,6}", row.株主コード) & " " & GetFormat1(row) & ←⑥ String.Format("{0,7:#,##0}", row.ポント残高)) Next End Sub '表示文字列の整形の会員共通処理 Private Function GetFormat1(ByVal mem As 会員Entity) ←⑦ Dim str As String str = String.Format( "{0,3} {1} {2} ", mem.会員コード, mem.姓, mem.名) str = Left(str + "・・・・・・・・・", 14) Return str End Function

註: 上記で使用される LINQ のクエリ式では、"Select m"のように、1 件分のデータ m を特に加

工せずに、そのまま返しています。Visual Basic では、特に 1 件分のデータを加工しないのな

ら、Select 句は不要ですが、ここでは分かりやすくするため、あえて明示しました。

①の FillStatistics3 メソッドは、社員会員の利用残高の集計、また、④の FillStatistics4 メソッドは、

株主のポント実績の集計を行っています。それぞれ、②と⑤では、「oc.会員」プロパテゖを参照

しています。

社員会員と株主会員も、社員であることには違いないので、「oc.会員」で参照すると、これらの派

生クラスンスタンスも含まれます。

また、③や⑤では、OfType メソッドを使用して、会員の中から、それぞれ社員会員、株主会員を抽

出する表記方法です。この 2 種類の派生クラスのンスタンスは、③と⑥で同じ GetFormat1 メソッ

ドに引数として渡り、⑦で共通情報部分を整形化して文字列に変換しています。ここで、⑦の引数の

型が会員 Entity になっています。オブジェクト指向の考え方では、会員 Entity の派生クラスンスタ

ンスは、この引数に渡すことができます (いずれの派生クラスも、会員であることに違いない)。この

結果、様々な名前の違うクラスを定義しても、それが会員 Entity クラスの派生クラスであれば、引き

続き、⑦のメソッドを使用することができるのです。

註:余力があれば、TestEF プロジェクトの Form1.vb 上のリストボックスに表示するように変更し

て、Form1.vb に入力して実験してみましょう。

註:この例では、テーブルの中に、社員会員で、かつ株主会員という兼任の「会員」が存在する可

能性があります。もし、兼任の会員が存在していた場合、単に「oc.会員」という参照をすると、

仕様上、NotSupportedException という実行エラーが発生します。というのは、「oc.会員」プロ

パテゖで参照する場合、派生クラスを含め、本来すべての会員ンスタンスを参照できるはずで

すが、テーブルの情報に応じて、社員会員ンスタンスであったり、株主会員ンスタンスであ

Page 39: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

39

ったりします。しかし、「oc.会員」では、常に主キーで各ンスタンスをユニークに識別できな

ければならないので、一人の会員について、社員会員ンスタンスと株主社員ンスタンスは、

同時に 2 つ存在できないのです。しかし、上記プログラムの②や⑤のように、派生クラスのン

スタンスの種類を限定するのであれば、問題ありません。もちろん、複数の種類の派生クラス

に、1 つのンスタンスが属していなければ問題ありません。

・Table-Per-Hierarchy 継承 vs. Table-Per-Type 継承

ここで、改めて 2 種類の継承の特徴を確認します。

前者の Table-Per-Hierarchy は、LINQ to SQL の O/R デザナーと、Entity Framework のエンテゖテ

ゖデータモデルの両方でサポートしています。この方法では、1 つのテーブルの中だけで、基本クラ

スと派生クラスのデータが存在します。

そのため、派生クラスとしてゕクセスしても、1 つのテーブルだけゕクセスすればよいので、比較的

オーバーヘッドが少なくなります。その反面、1 つのテーブルの中に、ありとあらゆるものを詰め込

むので、無駄も増えや保守作業が多くなる可能性があります。たとえば、基本クラスとして 3000 件

のデータと、その派生クラスとして存在する 30 件のデータを 1 つのテーブルにまとめた場合、派生

クラスに必要な差分の列が、3030 件のデータに対して追加されます。この方法では、基本クラスが

使用しない無駄な列が存在します。さらに、派生クラスの種類が増えるごとに、基本クラスを含む元

のテーブルのスキーマを修正しなければなりません。

一方、後者の Table-Per-Type では、派生クラスの種類が増えても、基本クラスとなる元のテーブル

のスキーマを変更する必要はありません。派生クラスとしての差分の情報を持つ、追加のテーブルを

新規に定義するだけです。しかも、3000 件の基本クラスのテーブルのほかに、30 件の派生クラスの

テーブルが必要になった場合、追加するのは、その 30 件のテーブルだけです。その反面、派生クラ

スのンスタンスにゕクセスする場合、実質的に、リレーションシップで関連付いた複数のテーブル

にゕクセスすることになり、前者よりもオーバーヘッドが増える可能性があります。

これらのそれぞれの長所や短所を考慮しつつ、適用するシナリオに鑑みて、選択する必要があります。

註:ここまでに取り上げた一連の EDM デザナーの操作手順では、その背後で、相応の

ObjectContext のソースコード(オブジェクトレヤーのコード)が自動生成されます。Visual

Studio 2010 では新機能として、このオブジェクトレヤーの生成コードをカスタマズする新

しい方法が導入されました。EDM デザナーのコード生成の工程では、コード生成時のパラメ

ータや生成されるコードのパターンなどを記述する「T4 テンプレート」と呼ばれる構文を採用し

ており、独自の T4 テンプレートを記述すれば、カスタムコードを生成でます。

Visual Studio 2010 では、そのようなカスタマズのために、プロジェクトに追加できる項目と

して、「ADO.NET EntityObject ジェネレーター」と「ADO.NET Self-Tracking Entity ジェネレータ

ー」が新たに追加されました。この 2 つは、図 10 のダゕログボックスにも、追加項目として

列挙されています。

前者は、エンテゖテゖに関するカスタムコードを生成するための T4 テンプレートの雛型です。

Page 40: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

40

後者は、ObjectContext にキャッシュされたデータの変更を追跡するためのカスタムコードを追

加するためのものです。後者を利用して、独自の自己追跡機能を実装すれば、N 層の分散環境下

においての様々な層で ObjectContext を使用して変更を記録し、ネットワーク経由で

ObjectContext を受け渡し、その変更をデータベースに反映させることができます。詳細につい

ては、まずは以下のゕドレスを参照してください。

http://msdn.microsoft.com/ja-jp/library/ff477605.aspx

ADO.NET EntityObject ジェネレーターテンプレート

http://msdn.microsoft.com/ja-jp/library/ff477604.aspx

ADO.NET Self-Tracking Entity Generator テンプレート

モデルファーストによるデザイン

今回使用している AWSC サンプルプログラムでは、既にリレーショナルデータベースが存在すると

いう前提に立ち、EDM ウゖザードで逆に概念モデルを生成する手法を取りました。この方法は、既

存資産のリレーショナルデータベースを ADO.NET Entity Framework に適用させる上で役立ちます。

一方、.NET Framework 4 および Visual Studio 2010 では、 ADO.NET Entity Framework でのモデルフ

ゔーストがサポートされており、先に EDM デザナーで概念モデルを設計し、それを元に SQL

Server データベースに相応のスキーマを自動生成できるようになりました。ここでは、EDM デザ

ナーに関する最後の説明として、モデルフゔーストを用いてデータベースにスキーマを生成する方法

を確認します。

このあと示す手順では、前述の TestEF プロジェクトを使用します。また、予め空の SQL Server デー

タベースを作成しておいてください。ここでは、TestMFirst という名前の空のデータベースを使用す

ることにします。

・空のモデルの新規作成

まずは、TestEF プロジェクトの中に、新規に .edmx フゔルを作るところから始めます。(つまり、

今回は既存の AWSC.edmx フゔルを使用しません。)

1. TestEF プロジェクトを開いた状態にして、[プロジェクト] メニューの [新しい項目の追加]

をクリックします。[新しい項目の追加] ダゕログボックスが開いたら、「ADO.NET

Entity Data Model」をクリックして、フゔル名は「TestMFirst.edmx」と指定し、[追加]

をクリックします。

2. Entity Data Model ウゖザードが起動したら、今回は次図のように、「空のモデル」を選

択して、[完了] ボタンをクリックします。

Page 41: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

41

図 24. 「空のモデル」を選択

3. すると、次の図 25 のように空の状態の EDM デザナーが開きます。ここで今回は、デ

ザナー内の余白部分をクリックしモデル全体を選択した状態にして、プロパテゖウゖ

ンドウでは、図 26 のように「新しいオブジェクトの複数化」プロパテゖを True に設定

しておきます。

図 25 空の状態の EDM デザイナー

Page 42: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

42

図 26 「新しいオブジェクトの複数化」プロパティ

この「新しいオブジェクトの複数化」プロパテゖは、図 13 の EDM ウゖザードにある [生成されたオ

ブジェクトの名前を複数化または単数化する] チェックボックスに相当するプロパテゖです。今回は、

エンテゖテゖは単数形の名前、エンテゖテゖの集合 (エンテゖテゖセット)は複数形の名前にすること

にします。

・概念モデルのエンティティの新規作成

次にエンテゖテゖを新規に追加します。

1. EDM デザナー上で右クリックして、ショートカットメニューを表示させ、[追加] メニ

ューの [エンテゖテゖ] をクリックします。

2. [エンテゖテゖの追加] ダゕログボックスが表示されたら、次図のように、「エンテゖテ

ゖ名」には「Program」と入力します。すると、「エンテゖテゖセット」が自動的に

「Programs」(複数形)になることを確認します。また、キープロパテゖの「プロパテゖ名」

として、「プログラムコード」と入力し、「プロパテゖの型」は「String」選択します。

設定が済んだら、[OK] をクリックします。

Page 43: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

43

図 27 エンティティの追加

3. すると、次図のように EDM デザナーには、「Program」エンテゖテゖが追加され、

「プログラムコード」という名前の主キー列が追加されます。(主キー列の先頭には、鍵

型のゕコンが付いています。)

図 28 追加された「Program」エンティティ

4. ここで、上図の「プログラムコード」列の部分をクリックして選択し、プロパテゖウゖ

ンドウでは次図のように、Uncode、固定長、および最大長のプロパテゖを設定します。

これは、参考までに既存の AWSC データベースの「プログラム」テーブルの「プログラ

ムコード」列と同じ設定をしたものです。

連動して複数形になる

Page 44: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

44

図 29 列のプロパティの設定

5. 次に、デザナー上で「Program」エンテゖテゖ内の上部タトルを右クリックし、ショ

ートカットメニューを表示させ、[追加] メニューの [スカラープロパテゖ]をクリックしま

す。すると次図のように、スカラー値の列が追加され、名前が編集可能な状態になるの

で、「プログラム名」と入力します。そして、他の場所をクリックして入力を確定しま

す。なお、この列のデータ型は、既定のまま「String」とします。(プロパテゖウゖンドウ

の「型」プロパテゖで、この列のデータ型が分かります。)

図 30 列(プロパティ)の追加

6. ここまでの入力で、「Program」エンテゖテゖが次図のようになったことを確認します。

(間違った名前で入力した場合、もう 1 回、この列名をクリックすれば、再度編集するこ

とが可能になります。)

図 31 完成した「Program」エンティティ

「プログラム名」と入力する

Page 45: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

45

7. 次に、もう 1 つ別のエンテゖテゖを作成します。今度は別の方法を使用します。ツール

ボックスから「エンテゖテゖ」をドラッグして、EDM デザナー上の空き領域へ、これ

をドロップします。次図のように、エンテゖテゖが 1 つ新規に追加されます。

図 32 ツールバーから新しいエンティティをドロップ

8. 追加したエンテゖテゖの上部タトルをクリックして、エンテゖテゖ全体を選択します。

このとき表示されるプロパテゖウゖンドウでは、次図のように、「名前」プロパテゖに

「Incident」と入力します。すると、「エンテゖテゖセット名」は自動的に複数形になっ

て「Incidents」となることを確認します。

図 33 エンティティ名の指定と自動的な複数化

9. また、デザナー上の「Incident」エンテゖテゖの「ID」列をクリックし、この列を選択

した状態にして、プロパテゖウゖンドウで、以下のプロパテゖを設定します。(これも参

考までに、AWSC データベースの「開催予定」テーブルの「開催コード」と同じ設定を

行ったものです。)

・名前: 開催コード

ドロップする

連動して複数形になる

Page 46: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

46

・型: String

・Unicode: True

・固定長: False

・最大長: 50

10. 次に列を追加するため、デザナー上で「Incident」エンテゖテゖ内の上部タトルを右

クリックし、ショートカットメニューを表示させ、[追加] メニューの [スカラープロパテ

ゖ]をクリックします。列が追加され、列の名前が編集可能な状態になるので、「日付」

と入力します。

11. 「日付」列をクリックし選択状態にして、プロパテゖウゖンドウでは「型」プロパテゖ

を「DateTime」に設定します。(参考までに、日付型に設定した例です。)

12. ここまで終了すると、EDM デザナーには次のように表示されることを確認します。

図 34 EDM デザイナーで 2 つのエンティティの追加が完了

・アソシエーションの設定

次に、上記の 2 つのエンテゖテゖの間で、ゕソシエーションを設定してみましょう。

1. EDM デザナー (TestMFirst.edmx)を開いた状態にして、ツールボックスの「ゕソシエー

ション」を 1 回クリックしてマウスボタンを放します。次に、「Program」エンテゖテゖ

をクリックして、マウスボタンを押したままドラッグして、「Incident」エンテゖテゖ上

でマウスボタンを放します。すると次図のように、ゕソシエーションを表す線が追加さ

れます。

Page 47: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

47

図 35 追加されたアソシエーション

ここでは、ゕソシエーションの設定をする際に、先にクリックした「Program」エンテゖテゖが 1 側

となり、「Incident」エンテゖテゖが多側になります。また、ゕソシエーションを設定したことで、

この図 35 のように、それぞれのエンテゖテゖの下部には、対応する相手側のオブジェクトを表すた

めのナビゲーションプロパテゖが追加されました。

この状態で、データベースを生成すると、2 つのエンテゖテゖに基づいて、2 つのテーブルが作成さ

れ、さらに、多側である「Incident」エンテゖテゖ(テーブル)には、1 側のテーブルの行を特定するた

めの外部キー列が自動的に追加されます。

既に触れたように .NET Framework 4 では、多側のエンテゖテゖにはナビゲーションプロパテゖ(オブ

ジェクト)だけでなく、外部キー列にマップしたプロパテゖ(スカラー値)を追加することができます。

(.NET Framework 3.5 SP1 ではできません。) ここでは実際に、多側の「Incident」エンテゖテゖに、

外部キー列を表すプロパテゖを追加してみましょう。

2. 「Incident」エンテゖテゖのタトル部分を右クリックし、ショートカットメニューの[追

加]メニューにある [スカラープロパテゖ] をクリックします。すると、列が追加されるの

で、次のプロパテゖを設定します。なお、この列は外部キーとして使用するので、この

列のプロパテゖは、「Program」エンテゖテゖの「プログラムコード」列の各プロパテゖ

と一致させる必要があります。

・名前: プログラムコード

・型: String

・Unicode: True

・固定長: False

・最大長: 50

3. 次のように、「Incident」エンテゖテゖには、「プログラムコード」列が追加されたこと

を確認します。

Page 48: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

48

図 36 「Incident」エンティティにプログラムコード列を追加

この時点では、追加した「プログラムコード」列には、外部キーとしての性格は備わっておらず、単

なるスカラー値のプロパテゖです。これを外部キーとして指定するには、次の操作をします。

4. EDM デザナー上で、「Program」エンテゖテゖと「Incident」エンテゖテゖを結ぶゕソ

シエーションをダブルクリックします。

5. すると次図のように、[参照に関する制約」ダゕログボックスが表示されるので、[プリ

ンシパル] ドロップダウンリストでは、1 側のエンテゖテゖである「Program」を選択し

ます。これによって「依存」の欄には、多側のエンテゖテゖである「Incident」が表示さ

れます。また、下半分の一覧では、「依存プロパテゖ」に「プログラムコード」と指定

します(これが外部キーになります)。設定が済んだら、[OK]をクリックします。

図 37 外部キーに関する指定

6. 念のため、[フゔル] メニューの [すべてを保存] をクリックして、ここまでの作業内容

を保存しておきます。

多側

1 側

Page 49: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

49

これで、概念モデルの「Incident」エンテゖテゖの「プログラムコード」プロパテゖは、実際のデー

タベース上の「Incident」テーブルの外部キーである「プログラムコード」列にマップされるように

なります。

・データベーススキーマの生成

それでは、ここまでに作成した概念モデルを利用して、データベースにスキーマを生成してみましょ

う。

1. EDM デザナーの余白部分を右クリックして、ショートカットメニューを表示させ、[モ

デルからデータベースを生成] メニューをクリックします。

2. すると次図のように、データベース生成ウゖザードが起動するので、接続に使用するデ

ータベースとして TestMFirst データベース(または、任意の空のデータベース)を選択し、

[次へ]をクリックします。

Page 50: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

50

図 38 データベース生成ウィザード

3. すると次図のように、この概念モデルをもとにデータベースのスキーマを生成するスク

リプトがプレビュー表示されます。問題があれば、[前へ] ボタンで戻ることもできますが、

ここでは、[完了] をクリックして確定します。

図 39 概念モデルに基づき生成されたスクリプトのプレビュー

4. するとスクリプトは確定し、「TestMFirst.edmx.sql」というフゔルになってエデゖター

が開きます。(このフゔルは、プロジェクトに追加され、ソリューションエクスプロー

ラ―でも確認できます。)

Page 51: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

51

図 40 概念モデルに基づき生成されたスクリプト

5. 念のため、[フゔル] メニューの [すべてを保存] をクリックして、ここまでの作業内容

を保存しておきます。

6. このスクリプトをもとにデータベーススキーマを作成するため、このスクリプトの編集

ウゖンドウ内で右クリックし、ショートカットメニューから、[SQL の実行] をクリックし

ます。

7. すると、改めて接続先のデータベースサーバーのンスタンスを問うダゕログボック

スが表示されるので、対象となるサーバーンスタンスを選択し、[接続] ボタンをクリッ

クします。

8. するとデータベースの作成が開始され、問題がなければ、スクリプトのエデゖターの下

半分には、次図のように「コマンドは正常に完了しました。」というメッセージが表示

されます。

Page 52: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

52

図 41 正常完了時のメッセージ

これで TestMFirst データベース内に、概念モデルに基づくスキーマが作成されました。ここで、SQL

Server Management Studio で確認すると、オブジェクトエクスプローラーには次のように表示され

ます。2 つのテーブル (Incidents と Programs)が生成され、また、概念モデルにはゕソシエーション

が設定されていたため、Incidents テーブルのプログラムコード列は、外部キー(FK)として設定されて

います。

図 42 生成されたテーブル

Page 53: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

53

なお、このように概念モデルに基づいて、データベースにテーブルを生成すると、それと同時に、

EDM デザナー側では、概念モデルとデータベースのテーブルとのマッピングが設定され、モデル

ブラウザーにも、概念モデルだけでなく、データベースのストレージモデル) が追加されます。

図 43 概念モデルとストレージモデル

ここまでは、EDM デザナーに関する様々な使用方法を確認してきました。このあとは、コードを

使用して、Entity Framework でのデータを操作する方法について主に取り上げます。

作成した概念モデル

生成されたストレージモデル

Page 54: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

54

Entity Framework の更新とトランザクション

この節では、Entity Framework の機能の中で、データベースの更新に係る機能を取り上げます。既に

触れたように、データベースを更新するには、ObjectContext を使用します。ここでは、この

ObjectContext を用いた更新方法について改めて確認します。

特に、AWSC サンプルプログラムには、トランザクション環境下で ObjectContext を使用した更新処

理が含まれます。この更新処理を題材に使います。

ObjectContext による更新

AWDac プロジェクトの DAHelper1.vb の中にある、Reserve_ByObjectServices メソッドを確認してく

ださい。ここには、Entity Framework 版 (Object Services) の予約登録を行う処理が書かれています。

この予約登録では、今までと同様に、空席数を管理する「開催予定テーブル」から、予約対処となる

特別プログラムの空席数を 1 つ減算し、さらに同時に、「予約テーブル」に予約情報を新規に追加し

ます。次にそのコードを示します。(一部、コメントを省略しています。)

例 12. Entity Framework による更新処理

Public Function Reserve_ByObjectServices( ByVal memid As Integer, ByVal sch As AWSCDataSet.開催結合情報Row, ByVal opt As AWSCDataSet.オプションRow, ByRef rid As Integer, ByRef stat As DAStatus) As Boolean Dim result As Boolean = False Try Using ts = New TransactionScope() ←① Dim oc As New AWSCEntities() '当該開催スケジュールの空席確認 Dim select1 = From p In oc.開催予定 Where p.開催コード = sch.開催コード Select p ←② Dim plan = select1.First() '1行分のデータが存在すことが前提 ←③ If plan.空席<= 0 Then ←④ stat = DAStatus.NoRoom Exit Try 'ts.Complete を呼び出さずに処理を中断するのでロールバック End If ←⑤ '当該開催スケジュールの空席減算 plan.空席 -= 1 ←⑥ '予約データの新規挿入 Dim rsv = 予約Entity.Create予約Entity( ←⑦ 0, memid, sch.開催コード, sch.プログラム料金, sch.消費税, opt.オプション料金, opt.消費税, sch.合計 + opt.合計, Date.Now) rsv.オプションコード = opt.オプションコード ←⑧ oc.AddTo予約(rsv) ←⑨

Page 55: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

55

oc.SaveChanges() ←⑩ '新規に割り振った予約番号を取得 rid = rsv.予約コード ←⑪ '正常終了に投票(Vote) ts.Complete() ←⑫ End Using 'トランザクションスコープを終了することで処理が確定 stat = DAStatus.Success result = True Catch ex As Exception ←⑬ stat = DAStatus.AccessFailed End Try ←⑭ '戻り値 Return result End Function

処理手順は、LINQ to SQL の DataContext に類似しています。

①のトランザクションや同時実行制御の対応については説明を保留にして、ここではデータ操作の手

順そのものに着目します。

この処理では、空席数を減算する前に、念のため最新の空席数を取得し、空席数が正の数であること

を確認しています。しかし、元々の ADO.NET の予約処理 (Reserve メソッド、Reserve_ByTranScope

メソッド) の場合の、空席数の確認方法と異なっています。

元々の ADO.NET の例では、次のようにスカラー値として、「空席」列を確認するだけでした。

SELECT 空席 FROM 開催予定 WHERE 開催コード = @sid

しかし、DataContext を使用した上記の例では、該当する空席数を持つ行を、1 件分まるごと読み込

みます。③の First メソッドは、②のクエリ式で取得するクエリ結果から、先頭行を丸ごと取得して

います。

このように行ごと取得する理由は、そのあとに続く空席数の「更新処理」のためです。DataContext

を用いて、特定の行を更新するには、あらかじめ当該データ(当該行)をまるごと読み込む必要があり

ます。つまり、更新対象のデータを、メモリ上の相応のオブジェクトにマップする必要があるのです。

②と③は、そのためのマップ処理を兼ねていたのです。この点は、LINQ to SQL の DataContext と同

様です。

ここでは、③のところで、更新対象の行は変数 plan に設定されます。その直後、④で空席数が残っ

ていること (正の数であること) を確認した後、⑥でメモリキャッシュのデータに対して、空席数を

減算しています。そして、実際にデータベースの更新は、後ほど⑩の SaveChanges メソッドの呼び

出しによって、他の更新と合わせて、まとめて行うことになります。

このように ObjectContext を用いた更新では、DataContext と同様に、一旦、対象データを読み込ん

で(オブジェクトにマッピングし)、メモリ上のオブジェクトに対して修正し、最後に SaveChanges メ

ソッド呼び出しによって、データベースを更新するという手順を取ります。

Page 56: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

56

新規挿入の場合も同様に、まず⑦で予約データのオブジェクトをメモリ上に新規作成します。ここで

は、ObjectContext 用に用意された、ヘルパーメソッドである Create 予約 Entity メソッドを使用しま

した。このヘルパーメソッドも、EDM ウゖザードや EDM デザナーによって自動生成されます。各

列に設定する値は、メソッドの引数として渡します。ただし、Null 値が許容された列は、このメソッ

ドの引数で設定できないので、⑧のように個々のプロパテゖに明示的に設定します。

なお、⑧で設定されているオプションコードは、予約エンテゖテゖの外部キーにあたるプロパテゖで

す。既に説明したように、このような外部キーにあたるプロパテゖを介して、直接的に外部きーに値

の設定ができるのは、.NET Framework 4 からの新機能です。以前は、外部キーに直接マップしたプ

ロパテゖが無かったので、ナビゲーションプロパテゖを介して設定する必要がありました。⑦から⑧

の部分についてナビゲーションプロパテゖを介して設定する従来の方法に書き換えると、次のように

なります。

例 13. ナビゲーションプロパティを介して、外部キーへ値を設定する

Dim rsv = 予約Entity.Create予約Entity( 0, sch.プログラム料金, sch.消費税, opt.オプション料金, opt.消費税, sch.合計 + opt.合計, Date.Now) rsv.会員 = oc.会員.Where( ←(A) Function(m) m.会員コード = memid).First() rsv.開催予定 = oc.開催予定.Where( ←(B) Function(s) s.開催コード = sch.開催コード).First() rsv.オプション = oc.オプション.Where( ←(C) Function(o) o.オプションコード = opt.オプションコード).First()

この例では、新規予約(変数 rsv)のプロパテゖに値を設定する(A)や(B)、(C)にある、会員プロパテゖや

開催予定プロパテゖ、オプションプロパテゖはナビゲーションプロパテゖです。EDM デザナーで

ゕソシエーションを設定した以上は、そのルールに従う必要があり、ナビゲーションプロパテゖには、

外部キー制約の条件を満たす有効なオブジェクトンスタンスを設定しなければなりません。

そのため、(A)、(B)、および(C)の代入文の右辺では、それぞれ外部キーに対応するテーブルの Where

メソッドを呼び出して、外部キーに対応する正しいンスタンスを求めています。本来、このような

新規データを登録するとき、外部キーの値が有効であるかは検証するはずなので、ロジックとしては、

適切であるという見方ができます。

ただし、外部キーの値が確実に正しいということが分かっていて、無条件で予約データを登録したい

のであれば、例 12 の⑧ように外部キーに当たるプロパテゖへ、直接的に値を設定するほうが簡潔で

す。

なお、(A)や(B)、(C)において、外部キーのデータを検索して取得せずに、新規作成したオブジェクト

を設定すると、新規挿入とみなされ、予約データを書き込むだけでなく、同時に、外部キーの参照先

のテーブルにも、新規挿入できます。ObjectContext は、オブジェクトに対する新規挿入や変更など

の追跡を内部的に行っているので、同じ内容のオブジェクトでも、データベースに問い合わせて取得

したものと、メモリ上で新規作成したものでは、異なる扱いをします。

⑨で「AddTo 予約」メソッドを使用して、メモリ上の予約テーブル相当の「oc.予約」プロパテゖに

追加し、そして⑩の SaveChanges メソッドの呼び出しで、データベースに反映します。

Page 57: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

57

また、今回の例でも、新規挿入と同時に、それに伴って割り振られた ID 値の取得を行っています。

⑦では、新規予約データにあたる予約オブジェクトを生成する際に、ID に当たる「予約コード」を

設定していません。そして、⑩の SaveChanges メソッドの呼び出しによって新規挿入されると、割

り振られた ID 値 (予約コード) は、メモリ上のオブジェクトにも反映されます。そして、⑪のところ

で、その ID 値(予約コード)を参照しています。

註:この例では、更新(UPDATE) と挿入(INSERT) を取り上げました。削除 (DELETE) についても、更

新と類似しており、一旦、削除対象をメモリに読み込んだ後、DeleteObject メソッドを呼び出し

ます。詳しくは、次のゕドレスを参照してください。

http://msdn.microsoft.com/ja-jp/library/bb738695.aspx

オブジェクトの作成、追加、変更、および削除 (Entity Framework)

また、ObjectContext (Object Services)による全般的な操作は、以下の機能リフゔレンスのページ

にある、一連のリンクを参照してください。

http://msdn.microsoft.com/ja-jp/library/bb399603.aspx オブジェクトのサービス (Entity

Framework)

ObjectContext と TransactionScope を使用した同時実行制御

前述の例 12 の更新処理において、トランザクションの観点から確認します。

ObjectContext でも、ローカルトランザクションと TransactionScope をサポートしています。ローカ

ルトランザクションを使用するには、ObjectContext の Connection プロパテゖで参照できる

Connection オブジェクトに対して、オープンした後、BeginTransaction を呼び出せば、その後

Transaction オブジェクトを取得できるので、コミットやロールバックの制御ができます。その点を

除けば、ADO.NET 編で取り上げた SqlTransaction オブジェクトの制御方法と同じです。ここでは、

より簡潔に表現できる TransactionScope を使用することにします。実際のコードで確認してみまし

ょう。

例 12 の①では、TransactionScope オブジェクトを作成し、トランザクション処理を行うブロックを

開始しています。このブロックの中に、ObjectContext によるデータ操作を記述すれば、トランザク

ションに参加できます。

ここでは、②の空席数の参照(SELECT)から、⑩の SaveChanges による空席数更新(UPDATE)と予約挿

入(INSERT)までが、1 つのトランザクションの中で行われます。トランザクションでは、データの整

合性を保つために、他から更新されないよう、自動的にデータがロックされます。つまり、②の参照

の時点で自動的にロックが開始し、他からデータが保護されるので、この例ではデータの競合は発生

しません。

たしかに、ObjectContext のデータキャッシュは、メモリ上の非接続型のオブジェクトですが、②の

参照から⑨の更新までは、トランザクションスコープの範囲内なので、実質的には接続型ゕプローチ

です。よって、②から⑨まではデータ競合を意識せずに更新できます。

Page 58: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

58

註: たしかに、この予約登録をするに当たり、現在の空き状況を確認した上で、予約申し込みを

する一連の作業は、非接続環境で行われます。たとえば、空き状況を照会した際には、空きが 30

人だったとします。この 30 人という情報はクラゕント側にキャッシュされます。そして、こ

の 30 人という情報を閲覧している間に、他から何人か申込し、サーバー側では 30 人から 25 人

に最新の空席数が変化したとします。このとき、空きは 30 人であると認識している人が予約登

録する場合、もし、キャッシュされた 30 人という情報を 29 人に変更して、データペースに反映

すれば、確かにデータ競合になります。つまり、サーバー側では、29 人と 25 人のどちらを採用

すべきか判断できません。しかし、このサンプルでは予約登録の際に、キャッシュした 30 人と

いう数字を破棄して、②のところで改めて最新情報を取得します。つまり、最新の空きである 25

人を認識でき、それを正しく 24 人へと更新できます。もっとも、さすがに、最新の空席数が既

にゼロになっていた場合に、減算して「-1」にすることは不適切なので、④では改めて空席数を

チェックしています。

次に、コミットとロールバックの制御を改めて確認します。

既に ADO.NET 編で触れたように、⑫の Complete メソッド呼び出しが、コミットに同意した合図に

なり、最終的にはトランザクションスコープを終了するタミング (Using ブロックから抜け出すタ

ミング) でコミットされます。

もし、このトランザクションスコープ内で実行エラーが発生した場合は、すぐに⑬の Catch ブロック

に移動し、トランザクションスコープを抜け出ます。このときは、Complete メソッドを呼び出して

いないので、ロールバックすることになります。

また、④の If 文でも、空席数がゼロならばロールバックしたいので、④から⑤の If ブロックの中で、

Exit Try を実行しています。この場合、⑭の End Try の次行まで移動することになります。このとき

も、Complete メソッドを呼び出さずに、トランザクションスコープを抜けるので、ロールバックし

ます。

以上、ObjectContext と TransactionScope を組み合わせた、トランザクション制御による更新を確認

しました。LINQ to SQL の DataContext と同様に、もともと、ADO.NET 編の Reserve メソッドや

Reserve_ByTranScope メソッドで行っていた更新処理に比べると、記述が非常に簡潔になっているこ

とが分かります。

Page 59: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

59

Entity Framework のデータバインディング

この節では、データバンデゖングについて取り上げます。

第 2 部で触れたように、データバンデゖングのデータソースとして対応できるか否かは、対象とな

るオブジェクトの種類によって異なります。Entity Framework の主要なオブジェクトである

ObjectContext は、データバンデゖングに対応しています。厳密にいうと、対応しているのは、

ObjectContext によるクエリ結果や、ObjectContext のプロパテゖとしてゕクセスできるオブジェク

トです。ここでは、このような形態別に実際のコード例を確認します。とくに、ObjectContext がプ

ロパテゖとして提供する、テーブル相当のオブジェクトとバンデゖングする場合、変更内容をデー

タベースに反映することも可能です。その際には、オプテゖミステゖック同時実行制御に係るデータ

競合の問題を考慮する必要があります。この問題に対処する基本的な方法も示します。

クエリ結果へのバインディング

まず、Entity Framework を利用したクエリ結果とバンデゖングを行います。既に、クエリ結果を取

得するコードは、AWSC サンプルプログラムに用意してあります。例 7 で取り上げた

MakeProgramsFilterList_ByLINQtoEntities メソッド (以下に再掲) では、クエリ結果として、Caption

列と Expression 列を持つ論理的なテーブルデータ (実際はオブジェクトの集合) を生成するコードを

確認しました。ここでは、このメソッドが生成したデータを使って、バンデゖングを行ってみます。

例 14. LINQ to Entities~クエリ結果を取得し、新たに型を作成~

'(★★代替版:Entity Framework - LINQ to Entities) 'プログラム検索の際のフゖルタで使用する項目のリストを作成 Public Function MakeProgramsFilterList_ByLINQtoEntities() As IListSource←④ Dim oc As New AWSCEntities() Dim query = From row In oc.プログラム←⑤ Select Caption = row.プログラム名, Expression = "プログラムコード ='" + row.プログラムコード + "'" Return CType(query, IListSource) End Function

このデータを利用しているフォームは、[プログラム空き状況照会] (ProgramInfo.vb)です。ここで、

AWWinApp プロジェクトの中の ProgramInfo.vb のソースフゔルを開いてください。(ソリューショ

ンエクスプローラー上で、ProgramInfo.vb を右クリックして、[コードの表示] をクリックします。)

この ProgramInfo.vb の ProgramInfo_Load ベントハンドラーには、コメントゕウトした形式で、す

でに前述のデータを使用するデータバンデゖングのコードが用意されています。次のように、既存

の ADO.NET のバンデゖングはコメントゕウトして、逆に LINQ to Entities 版のほうはコメントを解

除し、利用できるように変更しましょう。

例 15. LINQ to Entities のクエリ結果とのデータバインディング

'(★★ADO.NETの基本的な使用) 'フゖルタ用のプログラム一覧の作成とバンデゖング 'Dim table As DataTable = BLComp1.MakeProgramsFilterList() 'ProgramsList.ValueMember = "Expression"

Page 60: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

60

'ProgramsList.DisplayMember = "Caption" 'ProgramsList.DataSource = table 'ProgramsList.SelectedIndex = 0 : (省略) '(★★代替版:Entity Framework - LINQ to Entities) 'フゖルタ用のプログラム一覧の作成とバンデゖング Dim table As IListSource = BLComp1.MakeProgramsFilterList_ByLINQtoEntities() ProgramsList.ValueMember = "Expression" ProgramsList.DisplayMember = "Caption" ProgramsList.DataSource = table ProgramsList.SelectedIndex = 0

今まで取り上げた、ADO.NET 版や LINQ to SQL 版と並べると分かりますが、設定手順に特別な違い

はないので、理解する上での問題はないでしょう。基本的には、バンデゖングに必要なコントロー

ル側のプロパテゖに、必要な情報を設定するだけです。ここでは、DataSource プロパテゖにクエリ

結果を設定しています。クエリ結果にも、Expression 列や Caption 列があるので、それぞれ、

ValueMember プロパテゖや、DisplayMember プロパテゖの扱いは同じです。

これを実行すると、[プログラム空き状況照会] フォームのドロップダウンリストに、次図のように表

示されます。

図 44 LINQ to Entities のクエリ結果とのデータバインディング

ここで使用したデータソースは、新たにスキーマを定義して作成されたデータでした。

次項では、ObjectContext のテーブルに相当するオブジェクトに直接バンデゖングする方法を確認

します。

ObjectContext のオブジェクトとのバインディング

そもそも ObjectContext では、概念モデルのエンテゖテゖと、メモリ上にキャッシュされたオブジェ

クトがマッピングされており、概念モデルのエンテゖテゖは、物理データベースに相当するストレー

Page 61: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

61

ジモデルにマッピングされています。よって、結果的には、データバンデゖングによって、データ

ベースのデータを、ObjectContext 経由でユーザーンターフェスに表示することができます。

それでは、このメモリ上のオブジェクトとユーザーンターフェスとの間でバンドを行い、ユー

ザーンターフェスからデータベースへ変更を反映するには、どうすればよいでしょうか。この方

法を確認します。

ここでは、前節までに使用した TestEF プロジェクトの Windows フォームゕプリケーションを引き続

き使用します。

註:この後の検証では、フォームの体裁は、図 16 のように、ボタン 4 個とリストボックス 1 個、

テキストボックス 1 個が必要です。また、少なくとも AWSC.edmx には、プログラムテーブル用

のエンテゖテゖが定義されている必要があります。

それでは、ObjectContext の「プログラム」テーブルに相当するオブジェクトと、フォーム上のリス

トボックスおよびテキストボックスとの間で、バンデゖングの設定を行います。

1. フォームデザナー上のフォームのタトルをダブルクリックして、Form1_Load ベン

トハンドラーを生成します。

2. 次のように、Form1_Load ベントハンドラーの外側に、ObjectContext オブジェクトを

メンバ変数として定義します。また、Form1_Load ベントハンドラーの中には、バン

デゖングを行うコードを記述します。データソースは、「oc1.プログラム」を使用します。

例 16. ObjectContext の「プログラム」オブジェクトとのバインディング

Private oc1 As New AWSCEntities()←① Private Sub Form1_Load(ByVal sender As System.Object, ... ListBox1.ValueMember = "プログラムコード" ListBox1.DisplayMember = "プログラム名" ListBox1.DataSource = oc1.プログラム ←② TextBox1.DataBindings.Add("Text", oc1.プログラム, "プログラム名") ←③ End SUb

①のように、ObjectContext オブジェクトは、Form1_Load ベントハンドラーの外側に記述してく

ださい。この変数は、のちほど、別のベントハンドラーからも参照します。

②は、リストボックスでのバンデゖングの設定、③はテキストボックスのデータバンデゖングの

設定です。黄色の部分がデータソースです。今回は、プログラムテーブルにマップされたオブジェク

トを指定しています。

ここで、ビルドして実行してみましょう。すると、フォームが開く直前に、Form1_Load ベントハ

ンドラーが実行され、次図のように、このスポーツクラブのプログラム一覧が表示されます。

Page 62: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

62

なお、リストボックスで、任意の項目を選択すると、それに連動して、テキストボックスの内容も変

化します。前述の②と③のように、同一のデータを指定すると、Windows フォームでは、すべての

コントロールでゕクテゖブな選択項目が、連動して移動します。Windows フォームでは、ユーザー

ンターフェスレベルでのカーソル管理が備わっています。

図 45 リストボックスおよびテキストボックスと、プログラム情報とのバインディング

ここで、いずれかの項目について、テキストボックス上でデータ変更した後、リストボックスで別の

項目を選択してカーソルを移動してください。次図のように、リストボックスにも変更内容が反映さ

れます。以下の例では、テキストボックスで「パワーヨガ特別企画」と変更した後、リストボックス

で別の項目を選択した例です。

図 46 テキストボックスで修正して、カーソルを移動するとリストボックスにも反映

自動連携

テキストボックスで

「パワーヨガ A 特別企画」と入力

Page 63: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

63

このように連動して、テキストボックスの内容が、リストボックスに反映されるのは、共通のバン

デゖングの元となるデータソースが変更されたからです。

しかし、あくまで ObjectContext オブジェクトとのバンデゖングなので、このままではデータベー

スへは反映されません。試しに、このゕプリケーションを一旦閉じて、もう一度、起動してみてくだ

さい。すると、再び Form1_Load ベントハンドラーが実行され、データベースからデータが取り込

まれます。フォームのリストボックスに表示されるのは、図 45 の変更前の状態です。

ObjectContext オブジェクトでは、このオブジェクトのプロパテゖなどのゕクセスするだけで、必要

なデータは自動的にデータベースから読み込まれます。ADO.NET のように、TableAdapter を使用し

て読み込む必要はありません。しかし、データベースへの更新は、明示的に行う必要があるのです。

次に、この更新処理を実装します。ただし、非接続環境なので、データの競合などを考慮する必要が

あります。

オプティミスティック同時実行制御における操作

今回の状況での更新処理は、非接続の状態の「プログラム」データのキャッシュに関して、変更分を

データベースに書き込むものです。よって、他のユーザーがデータベースに変更を加えていた場合、

データの競合が発生します。データの一貫性を保ちつつ更新するには、オプテゖミステゖック同時実

行制御に基づく、データ操作を行う必要があります。

ObjectContext は、オプテゖミステゖック同時実行制御に対応することが可能です。この機能を使用

すると、ObjectContext では、以前にデータを読み込んで非接続状態でキャッシュしてあるとき、キ

ャッシュ内のデータを修正して、データベースへの更新を試みるとき、既に他のユーザーによって、

データベース側が以前と異なる内容に変更されていると、データ競合として例外を発生させます。

ここでは、簡潔な実装で工数をかけずに、テータの一貫性を保たせるため、更新時の際にトランザク

ション (TransactionScope) を実行し、競合が発生したら、すべてロールバックすることにします。

たとえば、非接続の状態で 4 件のキャッシュデータを変更した後、これの更新をデータベースに試み

たとします。2 件は更新に成功し、3 件目でデータ競合が発生したとします。この場合も、すべての

更新を無かったものとして、ロールバックすることにします。

TransactionScope を使用するには、System.Transactions.dll への参照設定が必要です。ここで、この

DLL (.NET ゕセンブリ) への参照を、この実験用ゕプリケーションのプロジェクトに追加しましょう。

(以下では、プロジェクト名を「TestEF」と想定しています。)

1. 引き続き使用中のプロジェクトについて、ソリューションエスクプローラ上の、プロジ

ェクト名「TestEF」を右クリックします。ショートカットメニューから、[参照の追加] を

クリックします。

Page 64: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

64

2. 次図のように、[参照の追加] ダゕログボックスが表示されたら、[.NET] タブをクリック

した後、[コンポーネント名] 一覧から「System.Transactions」をクリックして選択します。

図 47 System.Transactions への参照の追加

3. System.Transactions を選択したら、[OK] をクリックして、このダゕログボックスを閉

じます。

・オプティミスティック同時実行制御の準備~ EDM デザイナーでの指定~

エンテゖテゖデータモデルに基づく ObjectContext では、既定構成では、特別な同時実行制御を行い

ません。オプテゖミステゖック同時実行制御を行い、他のユーザーのデータ変更による競合を検出す

るには、エンテゖテゖデータモデル側で、そのように設定する必要があります。

この設定は、概念モデルのエンテゖテゖの中の、列単位で行います。列の「同時実行モード」プロパ

テゖを「Fixed」に設定する必要があります。

1. ソリューションエクスプローラーのツリー上で、TestEF プロジェクトの中の AWSC.edmx

フゔルをダブルクリックして、EDM デザナーで開きます。

2. デザナー上で、「プログラム」エンテゖテゖの「プログラム名」列をクリックして選

択して、この列のプロパテゖをプロパテゖウゖンドウに表示させます。

3. 次図のように、プロパテゖウゖンドウで、「同時実行モード」プロパテゖを、既定値の

「None」から「Fixed」に変更します。

Page 65: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

65

図 48 同時実行モードの指定

4. 念のため、ここまでの設定を保存しておきます。

・ObjectContext を利用したオプティミスティック同時実行制御

ここで、データベースに書き込むためのコードと、データの競合を解決するコードを入力します。

今回は、[Button3] をクリックすると、データベースの更新を行い、競合が発生したら、エラーメッ

セージが表示されるようにします。また、[Button4] をクリックすると、競合を解決する処理が起動

するようにします。

1. フォームデザナー上で [Button3] ボタンをダブルクリックして、Button3_Click ベント

ハンドラーを生成します。

2. 同様に、フォームデザナー上で [Button4] ボタンをダブルクリックして、Button4_Click

ベントハンドラーを生成します。

3. Form1.vb をコードエデゖターで開きます。この後、クラス名を使う際に、完全修飾名を

使用しなくて済むようにするため、Form1.vb フゔルの中の一番先頭に、次の Imports

ステートメントを追加します。これでクラス名の指定に、相対パスが利用できます。

例 17.名前空間のインポート

Imports System.Transactions 'TransactionScope のため

4. Button3_Click ベントハンドラーに次のコードを追加します。

例 18.ObjectContext による更新と、データ競合の対処

Private Sub Button3_Click(ByVal sender As System.Object, ... Try

Page 66: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

66

Using scope As New TransactionScope() ←① oc1.SaveChanges() ←② scope.Complete() ←③ End Using Catch ex As OptimisticConcurrencyException ←④ MsgBox("データの競合が発生しまた。競合を解決してください。" & vbCr & "すべてロールバックします。") Catch ex As Exception MsgBox("予期せぬエラーが発生しました" & vbCr & "すべてロールバックします。") End Try End Sub Private Sub Button4_Click(ByVal sender As System.Object, ... If MsgBox("サーバーの最新情報を取得しますか?" & vbCr & ←⑤ "([はい]を選ぶとクラゕントでの修正を破棄します)", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then oc1.Refresh(Objects.RefreshMode.StoreWins, oc1.プログラム) ←⑥ Return End If If MsgBox("クラゕントのデータで強制的に上書きしますか。", ←⑦ MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then Try Using scope As New TransactionScope() oc1.Refresh(Objects.RefreshMode.ClientWins, oc1.プログラム) ←⑧ oc1.SaveChanges() ←⑨ scope.Complete() End Using Catch ex As Exception MsgBox("予期せぬエラーが発生しました" & "すべてロールバックします。") End Try End If End Sub

データベースへの更新を試みるのは、②の SaveChanges メソッドです。

TransactionScope の使用方法は、今までと同じです。①でトランザクションスコープを開始して、ス

コープのブロックを終了する手前の③で、Complete メソッドを呼び出します。もし、例外が発生し

なければ、③を通過するはずです。

例外が発生した場合は、③を実行せずに、④または⑤の Catch ブロックに制御が移るので、ロールバ

ックすることになります。このうち、④はデータの競合が発生した場合の例外です。ここでは、その

旨が分かるように、表示すべきメッセージを他の例外である⑤と切り分けました。

後半の Button4_Click ベントハンドラーは、競合への対処です。ここでは、行う処理を分かりやす

くするため、ユーザーンターフェスとして、二択の単純なメッセージボックスを使用しました。

Page 67: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

67

まず、⑤の If 文では、サーバーから最新版のデータを取り込み、クラゕント側の変更分を破棄する

か問うものです。⑥の ObjectContext の Refresh メソッドを呼び出すと、サーバーのデータが再び読

み込まれて、既存のクラゕントのキャッシュは上書きされます。一番目の引数の「StoreWins」は、

サーバー側のデータが勝つことを意味します。このとき、二番目の引数には、読み込むべき範囲を指

定します。ここでは、プログラムテーブルを指定しています。

次の⑦の If 文では、競合が発生した際に、クラゕント側の変更分を使って、サーバー側へ強制的に

上書きすることを問うものです。⑧の Refresh メソッド呼び出しでは、一番目の引数に「ClientWins」

が指定されており、文字通り、クラゕント側のデータが勝つことを意味します。しかし、Refresh

メソッドでは、ObjectContext にキャッシュされた変更内容が直接サーバーに反映されるのではなく、

クラゕント側の内部で記録されているサーバーのオリジナルデータが、現在のサーバーの値で上書

きされます。つまり、クラゕントにしてみれば、サーバー側で他のユーザーが変更してないと見な

されます。そして、次に⑨のように、SaveChanges メソッドを呼び出すと、クラゕント側に記憶さ

れたサーバーのオリジナルデータと、実際のサーバーの値が同じなので、競合は無いものとみなされ、

クラゕントの情報は、サーバーに書き込まれます。

それでは実行して、変更の実験をしましょう。

1. 実験用のゕプリケーションを起動し、フォームが起動したら、テキストボックスから入

力して、リストボックス上の「プログラム名」を変更します。

2. [Button3] をクリックして、実行エラーがないことを確認します。

3. 一旦、ゕプリケーションを終了して、再度起動します。

4. ゕプリケーションは最新情報を読み取り、修正した通りに表示することを確認します。

さらに、データ競合の実験をしましょう。併せて、SQL Server Management Studio など、データベ

ースを変更できるツールを起動してください。

5. 実験用のフォームゕプリケーションを起動して、数件へ修正します。まだデータベース

には送信しません。[Button3] をクリックしないでください。

6. 次に、SQL Server Management Studio などから、この実験用ゕプリケーションが編集し

た複数件の行のうち、一行を修正します。

7. そして、実験用ゕプリケーションから、[Button3] をクリックして更新します。

8. 次のエラーメッセージが表示されることを確認します。

Page 68: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

68

図 49 データ競合の検出

競合が検出され、OptimisticConcurrencyException が発生しました。ここで、サーバー側のデータを

取り込むことで、競合を解決しましょう。

9. 上記の [OK] をクリックして、メッセージボックスを閉じます。

10. フォーム上で [Button4] をクリックします。次のメッセージボックスが表示されることを

確認します。

図 50 サーバー側のデータを取り込むかを問うメッセージ

11. [はい] をクリックして、メッセージボックスを閉じます。

12. フォーム上のリストボックスには、サーバー側で修正した結果が、表示されることを確

認します。

13. また、[Button3] をクリックしても、エラーメッセージが表示されないことを確認します。

今度は逆に、クラゕント側のデータを使って、サーバー側のデータへ強制的に上書きしましょう。

14. 念のため、ゕプリケーションを終了して、再び起動します。

15. フォーム上のテキストボックスから入力して、リストボックスのプログラム一覧のうち、

数件を修正します。まだ、[Button3] をクリックしません。

Page 69: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

69

16. サーバー側で、SQL Server Management Studio などから、この実験用ゕプリケーション

が編集した複数件の行のうち、一行を修正します。

17. [Button3] をクリックします。すると、手順 8 と同様に、競合のエラーメッセージが表示

されます。

18. [OK] をクリックして、メッセージボックスを閉じた後、[Button4] をクリックします。

19. サーバーのデータを上書きするか問うメッセージボックス (手順 10 を参照)が表示された

ら、今度は [いいえ] をクリックします。

20. すると、次のように、クラゕント側のデータで、サーバー側を上書きするか問うメッ

セージボックスが表示されます。

図 51 クライアント側のデータでサーバーを上書きするか問うメッセージ

21. [はい] をクリックします。SQL Server Mangement Studio などを使用して、サーバー側の

データがクラゕント側のデータで上書きされたことを確認します。

以上、非接続でのデータ更新とデータ競合の検出、データ競合への対処方法について確認しました。

ObjectContext の SaveChanges メソッドと TransactionScope を使用すると、簡潔にオプテゖミステ

ゖック同時実行制御に対応できます。

Page 70: 第3部 SQL Server データゕクセス手法(3)download.microsoft.com/download/A/0/2/A020A964-9AC3-4142...2011/01/29  · データモデリングの手法 第1 部で触れたようにエンテゖテゖデータモデルでは、次図のように、物理的なストレージからは独

70

まとめ

第 3 部の ADO.NET Entity Framework 編では、ADO.NET Entity Framework を用いた具体的な実装方法

や Visual Studio 2010 の使用方法について取り上げました。AWSC サンプルプログラムを使用して、

1 つのゕプリケーションの中で、その用途や実装箇所を確認しました。そして、簡単な実験用のゕプ

リケーションを構築し、基本的な実装方法やキーとなる機能について確認しました。

また、従来の ADO.NET のコードや、LINQ to SQL との比較を通じて、その差分や特徴について確認

しました。

さらに、単にクラスラブラリを使用するだけでなく、Visual Studio 2010 を有効活用することを踏

まえ、Entity Data Model デザナーを使用し、ゕソシエーションの設定や継承クラスの設定など、

モデリングでの設定が、ソースコードにおいてどう反映されるかを確認しました。また、.NET

Framework 4 における ADO.NET Entity Framework の新機能のいくつかを確認しました。

ここでは、Entity Framework が提供するすべての機能を網羅的に解説したわけではありません。しか

し、このサンプルを使用して、主要な利用の形態ごとに、その特徴や実装する上での注意点や、取り

組む上での着眼点、ヒントなどを確認しました。

本書で取り上げた内容が、Entity Framework を今後使用する上で、役立って頂ければ幸いです。