RSS

Advent LINQ (21) : LINQプロバイダー

21 12月

IQueryableには、何らかのLINQプロバイダーが関連付けられている。AsQueryableを使用してIQueryableに変換したクエリは、以下のように「EnumerableQuery<T>」というLINQプロバイダーが割り当てられている。

LinqProvider

IQueryableインターフェイスとLINQプロバイダーの関係や、プロバイダーの作成方法については、チュートリアル : IQueryable LINQ プロバイダの作成にまとまっている。やや難解であるので、読み合わせ的に補足していこうと思う。


想定しているシナリオ

「TerraServer-USA Web Services」というサービスが存在したとして(実際あるようだが、何故か応答が返ってこない)、そのウェブサービスに対してクエリを発行し、結果を取得出来る。何もない状態では、WCFで定義されたインターフェイスに従って、メソッド呼び出しのような形式でサービスを利用するが、このサービスに対応するLINQプロバイダを書けば、LINQクエリの記述でサービスを利用する事が可能になる。つまり、既存のWCFインターフェイスを使用して、「LINQ to TerraServer」を作ると言う事になる。
TerraServerWebService


全体的な構造

LINQクエリを記述する側は、IEnumerableやIQueryableといったインターフェイスにだけ注目する。LINQプロバイダーを作る場合(そして、LINQ to SQLやLINQ to Entities)は、IQueryableインターフェイスを実装した独自のクラスを用意する。と同時に、LINQプロバイダーとなる「IQueryProvider」インターフェイスを実装したクラスも用意する。このクラスが、LINQクエリーのExpressionを解釈し、SQL文を生成したりする。今回はWCFを使用して、TerraServerのサービスにアクセスする。
OverallClasses
また、LINQクエリの記述を成立させるには、結果を格納するエンティティとなるクラスが必要だ。例えば、

using (var context = new AdventureWorksLT2012_DataEntities())
{
	// CustomerAddressエンティティクラスが受け皿となるクエリ
	IQueryable<CustomerAddress> persons =
		from customerAddress in context.CustomerAddress
		where customerAddress.AddressType == "Shipping"
		select customerAddress;
}

このようなクエリが(RDBやWCFを通じてサーバーで)実行され、結果が返される。その結果をこのクラスに格納する。そのため、クラスの定義が必要となる。

もう一つ、LINQ to SQLやLINQ to Entitiesでは、「コンテキスト」と呼ばれるRDBへの接続を管理するクラスも必要だ。これがないと、LINQソースとなる端点(上記の例であれば、context.CustomerAddress)が提供出来ないので、クエリが書けない。但し、別の方法もある。普通の列挙子をAsQueryableでIQueryableに変換した場合は、コンテキストとなるクラスは存在しない。つまり、何らかの方法で、LINQソースとなる端点が提供できれば良いと言う事だ。

広告
 
コメントする

投稿者: : 2013/12/21 投稿先 .NET, LINQ

 

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。