「TerraServer-USA Web Services」というサービスが存在したとして(実際あるようだが、何故か応答が返ってこない)、そのウェブサービスに対してクエリを発行し、結果を取得出来る。何もない状態では、WCFで定義されたインターフェイスに従って、メソッド呼び出しのような形式でサービスを利用するが、このサービスに対応するLINQプロバイダを書けば、LINQクエリの記述でサービスを利用する事が可能になる。つまり、既存のWCFインターフェイスを使用して、「LINQ to TerraServer」を作ると言う事になる。
全体的な構造
LINQクエリを記述する側は、IEnumerableやIQueryableといったインターフェイスにだけ注目する。LINQプロバイダーを作る場合(そして、LINQ to SQLやLINQ to Entities)は、IQueryableインターフェイスを実装した独自のクラスを用意する。と同時に、LINQプロバイダーとなる「IQueryProvider」インターフェイスを実装したクラスも用意する。このクラスが、LINQクエリーのExpressionを解釈し、SQL文を生成したりする。今回はWCFを使用して、TerraServerのサービスにアクセスする。
また、LINQクエリの記述を成立させるには、結果を格納するエンティティとなるクラスが必要だ。例えば、
using (var context = new AdventureWorksLT2012_DataEntities())
{
// CustomerAddressエンティティクラスが受け皿となるクエリ
IQueryable<CustomerAddress> persons =
from customerAddress in context.CustomerAddress
where customerAddress.AddressType == "Shipping"
select customerAddress;
}
このようなクエリが(RDBやWCFを通じてサーバーで)実行され、結果が返される。その結果をこのクラス(CustomerAddress)に格納する。そのため、クラスの定義が必要となる。
もう一つ、LINQ to SQLやLINQ to Entitiesでは、「コンテキスト」と呼ばれるRDBへの接続を管理するクラスも必要だ。これがないと、LINQソースとなる端点(上記の例であれば、context.CustomerAddress)が提供出来ないので、クエリが書けない。但し、別の方法もある。普通の列挙子をAsQueryableでIQueryableに変換した場合は、コンテキストとなるクラスは存在しない。つまり、何らかの方法で、LINQソースとなる端点が提供できれば良いと言う事だ。
バイナリのカバレッジデータを変換するMSBuildタスクのプラグイン「VS Coverage to XML Converter MSBuild task」は、VS2008に対応したコードだ。調査を続けると、どうもカバレッジデータを読み取るDLLが、Visual Studioのバージョン毎に違っている。おまけに、VS2010からは大幅に仕様が変更されており、ファイルが全く認識されない。
「VS Coverage to XML Converter MSBuild task」のソースコードを見ると、ライブラリを呼び出してバイナリデータをXMLに変換している。何のことは無い、バイナリデータがDataSet(インメモリのテーブルコレクション)に変換されるので、DataSet.WriteXmlでデータセット形式のXMLで書き出しているだけだ。