印刷用ページ       送信     
クリックして評価とフィードバックをお寄せください
 データ ポイント: Entity Framework に関する Q&a...
Related Articles

開発者は、ワークステーションおよび関連するクラスのバージョン管理にいつも頭を悩ませています。ワークフローのバージョン管理の主要な問題点と、ワークフロー定義、アクティビティ、およびワークフロー サービスへの変更に関する推奨事項について、Matt Milner が説明します。

Matthew Milner

MSDN Magazine May 2009

...

Read more!

Udi Dahan が、大規模な Software Plus Services 取引アプリケーションの開発中に、予測していなかった問題を彼らのチームがどのようにして識別し、乗り越えていったのかを説明します。

Udi Dahan

MSDN Magazine April 2009

...

Read more!

ドキュメントやマルチメディア アイテムのような大きい BLOB をデータベースとファイル システムのどちらに格納すればよいかは、常に意見の分かれるところです。SQL Server 2008 ではどちらかを選択する必要はありません。FILESTREAM 記憶域は両方の方法の長所を備えています。

Bob Beauchemin

MSDN Magazine May 2009

...

Read more!

この記事では、Windows サービス ベースのソリューションと SharePoint を連携させる方法について説明します。サービス インスタンスのプロビジョニング、起動、停止、削除といった操作を、SharePoint 3.0 サーバーの全体管理を通じて行う方法が紹介されています。

Pav Cherny

MSDN Magazine April 2009

...

Read more!

メモリ使用量はアプリケーションの実行速度に直接影響を及ぼす可能性があるため、最適化する必要があります。この記事では、.NET プログラムを対象に、メモリの最適化の基本について説明します。

Subramanian Ramaswamy および Vance Morrison

MSDN Magazine June 2009

...

Read more!

Also by this Author

John Papa が Silverlight 2 アプリケーションからのサービス呼び出しに関する質問に回答します。

John Papa

MSDN Magazine November 2008

...

Read more!

T-SQL では、ビューと派生テーブルは同じような目的で使用でき、それぞれの利点があります。ただし、SQL Server 2005 で使用する場合には、共通テーブル式 (CTE) という第 3 の選択肢があります。John Papa が説明します。

John Papa

MSDN Magazine October 2007

...

Read more!

John Papa が説明するように、SQL Server 管理オブジェクトは、開発者がデータベースのバックアップと復元、DDL コマンドの発行を行うための堅牢なツールセットを備えています。

John Papa

MSDN Magazine June 2007

...

Read more!

John Papa

MSDN Magazine November 2006

...

Read more!

今月は John Papa が、アプリケーション サーバーのデータにアクセスできるモバイル アプリケーションの開発に注目します。

John Papa

MSDN Magazine January 2008

...

Read more!

Popular Articles

This article introduces 10 development tools that can increase your productivity, give you a better understanding of .NET, and maybe even change the way that you develop applications. The tools covered include NUnit to write unit tests, Reflector to examine assemblies, FxCop to police your code, Regulator to build regular expressions, NDoc to create code documentation and five more.

James Avery

MSDN Magazine July 2004

...

Read more!

When incorporating the ASP.NET DataGrid control into your Web apps, common operations such as paging, sorting, editing, and deleting data require more effort than you might like to expend. But all that is about to change. The GridView control--the successor to the DataGrid-- extends the DataGrid's functionality it in a number of ways. First, it fully supports data source components and can automatically handle data operations, such as paging, sorting, and editing, as long as its bound data source object supports these capabilities. In addition, ...

Read more!

Microsoft patterns & practices の Composite Application Guidance for WPF で複合アプリケーションを作成する利点を紹介します。

Glenn Block

MSDN Magazine September 2008

...

Read more!

サイドバー ガジェットは小さいけれど強力なツールで、驚くほど簡単に作成できます。ここでは、Donavon West がその楽しさを教えてくれます。

Donavon West

MSDN Magazine August 2007

...

Read more!

WPF は、.NET Framework 3.0 の最も重要な新しいテクノロジの 1 つです。今月は、John Papa がそのデータ バインド機能について紹介します。

John Papa

MSDN Magazine December 2007

...

Read more!

データ ポイント
Entity Framework に関する Q&A
John Papa

コードのダウンロード : : DataPoints2008_05.exe (962 KB)
Browse the Code Online
この話題について私の所に寄せられた数百の質問から判断すると、開発者たちは、Entity Framework とそのデータ アクセスおよびモデリングの関係にたいへん興味を示しているようです。そのすべてに答えることはできないかもしれませんが、今月のコラムでは、いくつかのよく寄せられる質問に対して回答します。
Entity Framework を理解するための第一歩は、エンティティ モデリング、エンティティ モデルとリレーショナル データベースのマッピング、および Entity Data Model (EDM) のデザインを理解することです。この Q & A では、最初に ObjectContext を含む Entity Framework の基盤に関するいくつかの質問に回答した後、Entity Client と Entity SQL を組み合わせて使うことが適している場面について説明します。さらに、EntityClient と Object Services の違いについて説明し、LINQ および Entity SQL をこれらのサービスと共に使用する意味合いについて説明します。
また、Microsoft® .NET Framework を対象としたコードとネイティブ SQL コードの両方で作成されたクエリの分析も Entity Framework の重要な部分なので、生成された SQL を示しながら明示的な読み込みと一括読み込みについて説明します。サンプル コードとサンプル NorthwindEF データベースは、MSDN® Magazine Web サイトから、このコラムと共にすべてダウンロードできます。
LINQ を使用してエンティティにアクセスできるのになぜ Entity SQL を使用するのですか。 Entity SQL と EntityClient または Object Services の組み合わせを使用するプレゼンテーションを行うたびに、この質問を受けます (私には質問者を責めることはできません。これは、私自身が Entity Framework を使い始めたときに最初に頭に浮かんだいくつかの質問のうちの 1 つだからです)。LINQ の厳密な型指定とクエリ構文は非常に魅力的であり、開発者がエンティティを操作するための新しい言語の必要性に疑問を持つのは当然です。
この質問に対して十分な回答を示すためには、EDM を操作するために使用できる 3 つの主要な手法を最初に説明する必要があります。
  • EntityClient プロバイダを使用して Entity SQL クエリを作成する方法
  • Object Services を使用して Entity SQL クエリを作成する方法
  • Object Services を使用して LINQ クエリを作成する方法
これらの手法の間には、たとえば EntityClient プロバイダを直接的または間接的に使用するという共通の特徴があります。ただし、得られる結果と、その結果を得るための方法は異なります。
EntityClient プロバイダには、ADO.NET オブジェクト モデルの経験がある読者には馴染みのある一連のオブジェクトがあります。EntityConnection を使用して EDM に接続し、EntityCommand を使用して EDM に対してクエリを発行します。コマンドの結果は、DbDataReader を介して返されます。EntityClient を直接的に使用した場合も、または Object Services を介して間接的に使用した場合でも、最終的に EntityClient はクエリを発行して結果を返します。
さて、質問に戻りましょう。LINQ を使用してエンティティにアクセスできるのになぜ Entity SQL を使用するのでしょうか。その答えは、それぞれの手法の長所と短所にあります。

EntityClient + Entity SQL
インサイト : Entity Framework のデータの読み込み
多くのオブジェクト リレーショナル マッピング フレームワークでは、次に示す 2 つのよく知られた動作がサポートされています。これらの動作により、永続 "プラミング" コードを記述しないようにしたり、アプリケーションからデータベースへのアクセス回数および転送するデータの量を改善することが可能です。
一括読み込み プログラムが関連オブジェクトのセットを操作することが必要になるたびに、1 つの一括要求でグラフ全体がデータベースから取り込まれます。
遅延読み込み プログラムがオブジェクト グラフに接続するプロパティを操作すると、データが自動的にデータベースから読み込まれます。ストアに複数回アクセスする可能性がありますが、必要なデータのみが読み込まれます。
マイクロソフトのデータ プログラマビリティ チームがよく受ける質問 (そして私がかつて自問自答した質問) は、"Entity Framework で自動遅延読み込みがサポートされないのはなぜか" ということです (forums.microsoft.com/MSDN/ShowPost.aspx?PostID=644979 および forums.microsoft.com/MSDN/ShowPost.aspx?PostID=644808 を参照)。その答えは過去に起因しますが、将来に対しても影響があります。

歴史
2000 年に私が ADO.NET オブジェクト モデル (当時は ADO+ と呼ばれていました) に初めて触れたとき、データセットがたいへんすばらしいという印象を持ちましたが、接続型 API と非接続型 API がなぜ大きく異なるのかを理解できませんでした。私は、Microsoft .NET Framework の存在の前に、.NET ADO レコードセットの "場所の透過性" を忘れられないだろうと思いました。
その当時 .NET の習得に最も効果的な方法の 1 つは DOTNET ディスカッション リストを利用することだったので、私は質問をディスカッション リストに投稿しました (discuss.develop.com/archives/wa.exe?A2=ind0009B&L=DOTNET&D=0&I=-3&P=55148)。私の質問に対し、Omri Gazitt 氏が、「ネットワーク ラウンドトリップは開発者から隠されるべきではない」と答えてくれました。それは、当時の私にとって斬新なアイデアでした。実際のところ、これが ADO.NET の基本原理の 1 つです。当然、ADO.NET に基づいている Entity Framework も同じです。

現在
8 年後の今、Entity Framework チームは、たいへん成功した ADO.NET Framework の上に大がかりなデータ アクセス プラットフォームの最初のバージョンを準備しています。同じ原則の多くが今なお適用されていますが、さらに、私たちはこれを将来の強固な基盤にしたいと考えています。
"隠されたネットワーク ラウンドトリップの排除" という原則に基づき、Entity Framework では自動遅延読み込みはサポートされません。コードで生成したクラスから構成されたグラフをトラバースするという単独の動作では、ストアのクエリがトリガされることはありません。したがって、使用するオブジェクトはユーザー コードで明示的に取り込む必要があります。
処理の進行に応じて読み込みを行うことはできますが、その場合は、参照またはコレクションでその都度 Load メソッドを呼び出す必要があります。実際のところ、コード生成プロセスに介入したり、独自のクラスを作成したりすることで、暗黙的な遅延読み込みを実現することができます。
ただし、遅延読み込みを語るには、隠されたラウンドトリップだけでは足りません。プログラムで遅延読み込みを使用するたびに、一貫性のないデータを含むグラフになる可能性があることを知っておくことは重要です。また、プログラムがさまざまなデータを長時間にわたって更新することなく保持した場合、グラフに古いデータが含まれる危険性が生じます。
これと対照的な戦略である一括読み込みは、クエリ単位で完全にサポートされます。この手法では、クエリの対象に追加の関連エンティティを "含める" ための Include というクエリ ビルダ メソッドが明示的に使用されます。Include のパラメータは、ピリオドで区切られたナビゲーション プロパティのパスを含む文字列です。
通常、Include はソース テーブル間の JOIN クエリに変換されるため、たいていは転送によってデータが冗長になります。そのため、Include の使用には注意する必要があります。

—Diego Vega
マイクロソフト データ プログラマビリティ チーム、プログラム マネージャ

EntityClient API を使用してコードを記述すると、3 つの手法をきめ細かく制御できます。EDM に接続するための EntityConnection を作成し、Entity SQL でクエリを記述してそれを EntityCommand を使って実行し、その結果を DbDataReader を介して返すことができます。また、この手法は、LINQ や Object Services で提供される構文糖を一部省略することで、わずかながら軽量化されています。
Entity SQL の最大の長所は柔軟性です。文字列ベースの構文は、動的クエリの作成に適しています。アドホック クエリを作成する必要がある場合、これは非常に便利です。
ただし、この柔軟性と軽量化からもたらされる 1 つの影響として、結果を返すために必ず DbDataReader を経由する必要があります。EntityClient と Entity SQL の組み合わせを使用して EDM から純粋なエンティティを返すことはできません。DbDataReader を取得し、これを使用して Entity SQL クエリを満たす行のコレクションを反復処理することができます。図 1 に示すコードでは、Customers エンティティではなく、DbDataReader 経由で顧客レコードに対する反復処理を行っています。
ここで良いヒントを紹介します。デバッグ モードにおいて、列序数 X から読み取ることができないというエラーが出力される場合があります。このエラーはデバッグ モードでのみ発生し、デバッグ モードの自動ウィンドウを閉じることで回避できます。これは、Entity Framework Beta 3 の既知の問題です。
現在、Entity SQL と同等のデータ操作言語 (DML) は存在しません。つまり、EDM に対して Insert ステートメント、Update ステートメント、または Delete ステートメントを直接表現することはできません (図 2 を参照)。

Object Services + Entity SQL
Object Services を使用する 2 番目の手法は、Entity SQL を使用してクエリを実行する方法です。これは、(見えない部分でプロバイダとの通信を行いますが) EntityClient プロバイダとの直接的な対話から離れるやり方です。ObjectContext と ObjectQuery<T> を使用して、EDM に対するクエリを発行します。
この手法は、1 番目の手法と同様に、アドホック クエリを発行するのに適しています。ただし、Object Services と Entity SQL の組み合わせでは、DbDataReader を介してデータを返すのではなく、EDM からエンティティを返すことができます。これにより、安定した組み合わせの、第一級のエンティティを返す柔軟なクエリが実現されます。
現在、Entity SQL には DML 構造がないので、Entity SQL と Object Services を使用して Insert、Update、Delete の各コマンドを発行することはできません。ただし、この手法を使用して EDM からエンティティを取得した後、ObjectContext の SaveChanges メソッドを使用してエンティティを更新することは可能です。見てわかるように、次のコード サンプルでは、Customers のコレクションに対して反復処理を行っています。
string city = "London";
using (Entities entities = new Entities()) 
{
  ObjectQuery<Customers> query = entities.CreateQuery<Customers>(
    "SELECT VALUE c FROM Customers AS c WHERE c.Address.City = @city",
    new ObjectParameter("city", city)
  );

  foreach (Customers c in query)
    Console.WriteLine(c.CompanyName);
}

Object Services + LINQ
Object Services と LINQ を組み合わせて使用することは、アドホック クエリについては他の手法ほど適切ではありません。次のコード サンプルは、EDM から Customers のコレクションを返します。
string city = "London";
using (Entities entities = new Entities()) 
{
  var query = from c in entities.Customers
              where c.Address.City == city
              select c;

  foreach (Customers c in query)
    Console.WriteLine(c.CompanyName);
}
Entity SQL と同様に、LINQ でも DML ステートメントの直接構文がサポートされません。現在、Object Services を使用している場合は、(SaveChanges メソッドを使用して) データベースに対してエンティティを更新することのみが可能です。これは、Entity Framework で変更が追跡されている EDM からエンティティを返すことによって実現されます。つまり、LINQ と Entity SQL のどちらも更新操作を行いません。この操作を行うのは、EDM の ObjectContext です。
これらの手法の相違点を図 2 にまとめました。では、LINQ があるのになぜ Entity SQL を使用するのでしょうか。Entity SQL は、アドホック クエリが必要な場合や、LINQ では不可能なより柔軟なクエリを作成する場合に適した選択肢です。それ以外の場合は、厳密な型指定やエンティティと投影を返す機能のメリットを得られるように、LINQ と Object Services の組み合わせをお勧めします。
LINQ の厳密に型指定された構文に加え、アプリケーションの実行時でなければキャッチできない多くのエラーについてデザイン時のビューを得ることができます。私はこの機能をたいへん気に入っています。エラーをキャッチするためにビルドと実行を繰り返す必要なく、コードの記述に専念できるからです。
ObjectContext はどのような役割を持ちますか。 ObjectContext は、Object Services の EntityConnection のゲートウェイとして機能します。ObjectContext は、基になる EntityConnection を介して EDM へのアクセスを提供します。たとえば、ObjectContext を介してエンティティにアクセスしたり、オブジェクトの状態に関する情報を ObjectContext に問い合わせたりできます。さらに、CreateQuery メソッドを使用して ObjectQuery<T> クエリを作成することもできます。
ObjectContext のもう 1 つの目的は、オブジェクトがデータベース エントリに関する更新情報を取得するための方法を提供することです。たとえば、ObjectContext のメソッドを使用して、ObjectContext へのエンティティの追加、エンティティの削除、エンティティの操作などを行い、最終的に (SaveChanges メソッドを介して) エンティティの変更をデータベースに保存することができます。
Entity Framework で明示的な読み込みと一括読み込みはどのように動作しますか。 明示的な読み込みは、LINQ to Entities および Entity Framework における既定の動作です。Entity Framework 内でクエリが実行されたとき、クエリから返されたエンティティは完全にアクセス可能になりますが、関連付けられているエンティティの読み込みは即座には行われません。たとえば、EDM 内のすべての Orders を取得するクエリを作成した場合、SQL クエリは、注文レコードを取得して Orders エンティティのコレクションを返す処理の内部で実行されます。ただし、注文に関連付けられている顧客レコードはこのクエリの一部としてフェッチされないため、Orders エンティティに関連付けられている Customers エンティティは読み込まれません。したがって、次のコード サンプルの場合、Order の Customers にアクセスしようとしたときに Customers が読み込まれていないために例外をスローします。
using (Entities entities = new Entities())
{
  var query = (from o in entities.Orders
               where o.Customers.CustomerID == "ALFKI"
               select o).First<Orders>();

  Orders order = query as Orders;
  Console.WriteLine(order.OrderID);

  Console.WriteLine(order.Customers.CompanyName);
}
Entity Framework では、EntityReference クラスのそれぞれのインスタンスで Load メソッドが提供されます。このメソッドを使用すると、別のエンティティに関連付けられているコレクションを明示的に読み込むことができます。たとえば、Entity Framework を使って Order に対応する Customers レコードを取得するように前のコード例を変更できます。明示的な読み込みを実行するように書き直したコードを図 3 に示します。このコードでは、最初に Customers エンティティが読み込まれているかどうかをチェックします。読み込まれていない場合は、Order に対応する Customers レコードを読み込みます。この手法は、明示的な読み込みと呼ばれます。
図 3 の例では、SQL クエリを実行して、処理されたそれぞれの注文に対する Customer レコードを取得します。この手法で注文の反復処理を行う場合は、注文が数百でも、または数十であっても、データベースに対して別個のクエリを大量に発行することになります。クエリから返されるデータよりも多くのデータ (たとえば注文に対応する顧客情報) が必要になることが事前にわかっている場合は、この情報を前もって読み込むことができます。
このトピックに関する、Entity Framework を担当する Microsoft チームからのさらなる考察については、囲み記事「インサイト : Entity Framework のデータの読み込み」を参照してください。
図 4 は、一括読み込みと呼ばれる手法を示しています。LINQ クエリの Orders エンティティで呼び出される Include メソッドは、Orders と共に関連する Customers も取得するように指示する 1 つの引数を受け取ります。この方法では、LINQ クエリ内の条件を満たすすべての Orders および Customers を読み込む単独の SQL ステートメントが生成されます。
読み込み方式は、十分に検討する必要がある問題です。(図 3 に示すように) Load メソッドを使用して、コレクションに対する反復処理の間にエンティティを明示的に読み込む場合、(Load メソッドの呼び出しごとに実行される) いくつかのクエリがデータベースにアクセスすることになります。
これは、1 回か 2 回データにアクセスするだけで必要な作業を完了できる場合は、まったく申し分のない方法です。ただし、特定のエンティティに対して、関連するエンティティのデータに常にアクセスする必要があることがわかっている場合は、図 4 に示す Include メソッドを使用した一括読み込みの方が優れた選択肢です。
最善の方法は、任意の異なるオプションのパフォーマンスを測定およびテストして、自分のシナリオに最適な方法を見つけることです。ほとんどの決定事項と同様に、一括読み込みと明示的な読み込みのどちらを使用するかは、状況によって異なります。
実行される SQL を確認するにはどうしたらよいですか。 ObjectQuery を使用してクエリを作成したときに、どの SQL が実行されるかを調べたいと思ったことは何回もありました。そして、2 とおりの便利な方法を見つけました。1 つ目は、SQL Server® Profiler ツール (または、使用可能なデータベース エンジンのプロファイリング ツール) を使用する方法です。2 つ目は、ObjectQuery クラスの ToTraceString メソッドを使用する方法です。
図 5 に、ObjectQuery<T> で ToTraceString メソッドを呼び出す方法を示します。ObjectContext の接続が開いていることに注目してください (EntityConnection)。ToTraceString メソッドを実行するためには、実行するクエリを判定できるように接続が開いている必要があります。ToTraceString メソッドは、ObjectQuery<T> と EntityCommand クラスの両方で使用できます。
複合型を使用すると何ができますか。 Entity Framework は、複合型と呼ばれるデータ構造を提供します。複合型はプロパティのセットを表すもので、通常は互いに密接に関連しています。ここで、Address 型を考えてみましょう。複合型を使用して顧客の Address 型を作成することで、Customer エンティティの住所に関連するプロパティ (City、Region、Phone など) が直接 Customer 型ではなく、Address 型に分類されるようになります。複合型は、類似するスカラ プロパティの論理的なグループを提供します。これにより、エンティティの密接に関係するプロパティを見つけ出し、EDM で論理的にグループ化することが容易になります。エンティティと同様、複合型はスカラ プロパティを持ちます。また、エンティティとは異なりますが、複合型は ID (キー値) を持たず、ObjectContext を介してデータベースで保持することはできません。複合型は、エンティティ自体ではなく、エンティティの一側面です。複合型は、エンティティの論理的に関連するプロパティをグループ化する場合に優れたツールです。
複合型を作成する方法を教えてください。 現在、EDM デザイナは複合型のビジュアルな作成をサポートしていないため、複合型を作成するには、EDMX ファイルを XML エディタで開く作業が必要になります。最初の手順では、概念スキーマ定義言語 (CSDL : Conceptual Schema Definition Language) を使用して ComplexType を作成し、複合型を参照する EntityType を変更します。図 6 は、新しく作成された AddressType 複合型を含む、CSDL で記述された Customers EntityType を示しています。Customers EntityType にあった Address、City、Region、およびその他の住所に関連するプロパティが削除され、Address という新しいプロパティで置き換えられていることに注目してください。この新しい Address プロパティは、AddressType 複合型を参照します。
次の手順では、マッピング仕様言語 (MSL : Mapping Specification Language) を使用して、新しい複合型を反映するようにマッピングを変更します。図 7 は、新しい AddressType 複合型を含む、Customers EntityType のマッピングを示しています。プロジェクトをビルドした後はコードで複合型を参照できます。たとえば、次の LINQ クエリを実行すると、London に居住する顧客のみをフィルタ選択できます。
var query = from c in entities.Customers
            where c.Address.City == "London"
            select c;

まとめ
今月のコラムでは、EntityClient と Object Services、Entity SQL、LINQ の使い方を比較しました。さらに、複合型を作成する方法とその理由について触れ、一括読み込みと明示的な読み込みの動作を紹介しました。Entity Framework については、意欲的な開発者の皆さんからたくさんの質問が寄せられているので、将来の「データ ポイント」で同じようなトピックや実用的なヒントを紹介する予定です。

ご意見やご質問は、John まで英語でお送りください。 mmdata@microsoft.com.


John Papa は、ASPSOFT (aspsoft.com) で働く上級 .NET コンサルタントです。野球を熱狂的に愛し、夏の夜のほとんどを家族および忠犬 Kadi (カーディ) と共にヤンキースのために費やします。C# MVP であり、INETA の講演者でもある John は、ADO、XML、および SQL Server に関して何冊かの書籍を執筆しています。また、主に業界のカンファレンス (DevConnections、VSLive など) での講演やブログ (johnpapa.net) などで活躍しています。

Page view tracker