Silverlightのデータ処理
ご存じの通り、Silverlightはクライアントのブラウザ上で動作するため、サーバーアプリケーションとの間にはインターネットが存在する可能性があります。そのためSilverlightアプリケーションは、基本的にリレーショナルデータベース(RDB)と直接の接続は不可能であり、データベースとの相互のやりとりはWebサービスを経由して行うことになります。
一口にWebサービスと言っても、昨今のWeb環境では多くのサービスが存在します、身近なところでは、ブログの更新情報を入手するためのRSSフィードなどもWebサービスの一種あり、そうした情報をSilverlight上で活用することも考えられますが、RDBとの連携を考えた場合、現実的に選択できるのは以下の2種類になるでしょう。
- Windows Communication Foundation(ASMXを含む)Core Services
- ADO.NET Data Services(WCF Data Services、注1)
PDCにおいて、ADO.NET Data Servicesは今後「WCF Data Services」と名称変更されることが発表されました。
これは言い換えると、WCFが使用するプロトコルがSOAPであり、ADO.NET Data Servicesが用いるアーキテクチャパターンがRESTであると言った、2つの代表的なWebサービスの方式をSilverlight開発で選択できるということになります。
REST形式のWebサービスは、扱う対象をWeb上のリソースとして扱うことになります。例えば、お天気サービスであれば、「今日の新宿の天気」や「1週間分の川崎の天気」などと言ったものがリソースになり、サービス利用者は自分が必要なリソースをリクエストします。
一方SOAPを用いたWebサービスは、上述のお天気サービスであれば「天気取得メソッド」「週間天気取得メソッド」といった形で、そのサービスで行いたいことをサービスとして公開する形になります。RESTは名詞的、SOAPを用いたWebサービスは動詞的と考えることも可能です
Webサービス(データサービス)の使い分け
では、前述した2つの種類のWebサービス(データサービス)をどのように使い分けるべきでしょうか? 当然ながら、絶対的な正解があるわけではありませんが、筆者は次のように考えています。
- 処理を伴う形のサービスを作成したい場合は、WCF(ASMX)
- データを汎用的にサービス化したい場合は、ADO.NET Data Services
WCFは基本的にSOAPを通じたメッセージ交換の仕組み(注2)が基本的な考え方であり、データベースが持つさまざまなデータを、サービス利用者が必要とする形で公開するには非常に手間がかかります。例えば、商品テーブルがあり、このテーブルのデータ処理を考える場合、データの取得、更新、追加、削除などをそれぞれサービスとして用意する必要が出てくるはずです。さらにサービス利用者が、商品データとその親となる商品カテゴリのデータを一括で取得したいなどと言ったリクエストをしたい場合、サービス提供者は新たなサービスを追加する必要があるかもしれません。
WCFでもREST形式のサービスを構築することも可能ですが、今回はあえて外して考えています。
また、SOAP形式のメッセージにはデータの可搬性にも難があると言えます。前述した、商品データで考えてみましょう。例えば注文テーブルは、商品データを利用しているとします。その場合、サービス利用者が商品のデータを扱う場合、同時に商品カテゴリや、注文などのデータも、まとめて必要になることもあるでしょう。そうした場合、データはツリーやオブジェクトグラフの形になりえますが、これをWCFで可搬しようとすると、含めるべきデータの範囲について悩みます。まとめて必要になる場合もあれば、任意のタイミングで合わせて必要となるかもしれないからです。WCFは非常に柔軟にサービスを構築できるのですが、こうしたデータそのものの扱いに難があると言えます。
一方ADO.NET Data Servicesは、REST形式のデータサービスであるため、URLをあたかもSQLと同じようにデータをリクエストするための記述言語として扱うことが可能です。以下をご覧ください。
Jobsエンティティの全データを取得 http://localhost/pubsService.svc/jobs job_descフィールド昇順並び変え http://localhost/pubsService.svc/jobs?orderby=job_desc Job_idが15よりも大きなデータを取得 http://localhost/pubsService.svc/jobs?$filter=(job_id)gt(15) 上位2件かつ1件スキップしたデータを取得 http://localhost/pubsService.svc/jobs?&$top=2&$skip=1 キーのデータが2のmax_lvlフィールドの取得 http://localhost/pubsService.svc/jobs(2)/max_lvl
詳細は次回の連載記事に示したいと思いますが、ADO.NET Data Servicesでは、公開されるエンティティ(テーブル)は、基本的にCRUD(Create Read Update Delete)の機能が実装されます。そして、上記のようにURLとして、あたかもSQLで言うWhere条件句(filter)を書いたり、さらに、そのテーブルに関連するデータを任意のタイミングで取得したりすることも非常に容易です。逆に、ADO.NET Data Servicesが苦手とするのは、データに対して複雑な処理(バッチ的な考え方)を伴う場合です。
下記に、この2つのデータサービスのトレードオフとなる部分を表に書き出してみました。
メリット | 複雑な処理(異なるデータソースのマージ結果の取得)などが実装可能 |
デメリット | クライアントの変更管理を実装する必要がある |
サービス参照のエンドポイントが多くなる可能性がある |
メリット | クライアントの変更管理が可能 |
サービス参照のエンドポイントが一つ | |
クライアントの設定ファイル管理が容易 | |
デメリット | 複雑な処理(複数テーブルのデータ取得、1:N レコードの一括更新)では実装が冗長 |
こうした考え方に基づいて、前述したサンプルシステムでは次のようなアーキテクチャ概略の構成をとっています。単なるエンティティ(テーブル)データのCRUD処理は、ADO.NET Data Servicesで、OLTP処理(このサンプルではストアドプロシージャ呼び出しの実装)はWCFでサービスを構成しています。