特集:Visual Studio 2008 SP1新機能解説(3)

RESTスタイルのWebサービスを手軽に公開する
「ADO.NET Data Services」

WINGSプロジェクト 土井 毅 著/山田 祥寛 監修
2008/12/12
Page1 Page2 Page3

ADO.NET Data Services概要

 Visual Studio 2008 SP1(以降、VS 2008)で追加されたADO.NET Data Services(ADO.NETデータサービス)は、データベースをRESTスタイルのWebサービスとして公開するためのフレームワークである。ADO.NET Data Servicesを使うことで、RIA(Rich Internet Application)などのクライアント・アプリケーションやマッシュアップ・サーバなどへのデータベース公開を実現することができる。

新機能がてんこ盛りの「Visual Studio 2008 SP1」レビュー
VS 2008 SP1新機能解説(1)「ASP.NET Dynamic Data」
VS 2008 SP1新機能解説(2)「ASP.NET Entity Framework」

 本稿ではまず前半でADO.NET Data Servicesの概要について述べ、後半では実際にADO.NET Data Servicesを使ってデータを公開するWebサービスおよび、そのデータにアクセスするASP.NET AJAXアプリケーションをサンプルとして作成する。

■ADO.NET Data Servicesとは

 ADO.NET Data Servicesを1文で定義するならば、

REST(Representational State Transfer)スタイルのHTTP通信を介して、データベースの内容をAtom(Atom Publishing Protocol)/JSON(JavaScript Object Notation)形式で読み書きする機能

となる。つまり、ADO.NET Data Servicesは何かこれまでに存在しなかった新たな機能を実現するものではなく、より少ない手順で上記の機能を作るためのフレームワークといえる。

 もちろんADO.NET Data Servicesを用いることなく、データベース内の特定のテーブルの読み書き機能をWCF(Windows Communication Foundation)やASP.NETを使ってWebサービスとして公開することは可能である。しかし、ADO.NET Data Servicesを使うことで、定型的なコーディングを減らし、多彩な機能を実現することができる。

 例えば、RIAやマッシュアップ・サービスのための「電話帳サービス」を公開するシナリオを考えてみよう。

【シナリオ例】 電話帳サービス

 当初は電話帳の項目(以下、コンタクト)の一覧取得、詳細取得、新規作成、更新、削除機能を定義し、Webサービスとして公開した。

 しかし機能要件が変化し、コンタクトをカテゴリごとに取得する機能や、ソートして取得する機能が必要になった。さらに、クライアントでのページング表示のため、すべてのサービスについて、特定の件数単位で取得する機能が必要になった。さらに、データの出力形式について、XMLだけでなくJSONにも対応しなければならなくなった。

 独自にWebサービスを作成していた場合、このような機能要件の変化への対応はかなりの作業が発生する。カテゴリごとのコンタクト一覧取得は、また新たなAPIを作る必要があるだろう。また、ソートや特定の件数単位での取得を全サービスで実装するには、(定型的ではあるものの)すべてのサービスに対してのコーディングが必要になる。一方ADO.NET Data Servicesを使えば、こうした機能を(複数の機能の組み合わせも含め)わずかなコーディングで実現可能となる。

 RIAやマッシュアップ・サービス向けにデータベースを公開するWebサービスは、それ自体がサービスの花形、主役であるというよりも、サービスを支える縁の下の力持ちと位置付けられる。一方で、いかにクライアントから利用しやすい機能を実現するか(=たくさんマッシュアップしてもらえるか)、セキュリティを担保するか、という点も重要となる。

 ADO.NET Data Servicesを使うことで、多彩な機能をわずかな設定で実現でき、素早いサービス展開を行うことができる。

■ADO.NET Data ServicesとREST

 前述の定義に出てきたRESTはADO.NET Data Servicesを理解するうえで重要な概念である。RESTは明確に定められた仕様ではないため、何をRESTと呼ぶかについてはさまざまな主張が存在するが、ADO.NET Data Servicesとの関連においていえば、以下の原則が重要である。

1.ステートレス

 ADO.NET Data Servicesは、クッキーなどによってセッションを維持する必要がない、ステートレスな通信を実現する。

2.リソースを一意に識別するための識別子を持つ

 ADO.NET Data Servicesでは、リソース(=データベースのテーブルやレコード、フィールドなど)の特定をURI形式により行う。

3.リソースを操作するためにHTTP動詞を用いる

 ADO.NET Data Servicesでは、データベースに対する参照、挿入、更新、削除(SQLではそれぞれSELECT、INSERT、UPDATE、DELETE句に対応)処理を、それぞれ対応するHTTP動詞(GET:参照、PUT:挿入、POST:更新、DELETE:削除)を用いた通信で行う。

 例えば、先の事例における電話帳データベースを、“RESTスタイルでない”Webサービスで公開する場合、以下のようなAPIが考えられる。

URI HTTP
動詞
内容
/phonebook/getContacts GET 全コンタクトを取得する
/phonebook/getContactById?id=3 GET クエリ文字列で指定したIDを持つコンタクトを取得する
/phonebook/createContact POST POSTしたデータで新しいコンタクトを追加する
/phonebook/updateContact POST POSTしたデータでコンタクトを更新する
/phonebook/deleteContactById?id=1 GET クエリ文字列で指定したIDを持つコンタクトを削除する
/phonebook/getContactsFilterByCategory?CategoryID=2 GET クエリ文字列で指定したカテゴリIDを持つコンタクトを取得する
表1 RESTスタイルでないWebサービスでの電話帳APIの例

 RESTスタイルでないWebサービスにおいては、上記のとおり、対象とするリソースと操作の両方がURIに含まれている。

 一方、ADO.NET Data Servicesでは、以下のようなAPIとしてサービスを提供することになる。

URI HTTP
動詞
内容
/phonebook/Contacts GET 全コンタクトを取得する
/phonebook/Contacts(3) GET URIで指定したIDを持つコンタクトを取得する
/phonebook/Contacts PUT PUTしたデータで新しいコンタクトを追加する
/phonebook/Contacts POST POSTしたデータでコンタクトを更新する
/phonebook/Contacts(1) DELETE URIで指定したIDを持つコンタクトを削除する
/phonebook/Contacts?$filter=CategoryID eq 2 GET クエリ文字列で指定したカテゴリIDを持つコンタクトを取得する
表2 ADO.NET Data Services(RESTスタイル)での電話帳APIの例

 ADO.NET Data Services(=RESTスタイルのWebサービス)では、この表2にあるようにURIは対象とするリソースを表し、HTTP動詞は操作を表す。URIがリソースの指定に専念しているため、シンプルになっている点に注目していただきたい。

 なお、リソースを特定するためのIDはURI自体に含まれるが、後述のフィルタやソートなどのオプション機能は、それ自体が対象リソースを指定するものではなく、見掛け上の制御を行うための情報であるため、クエリ文字列内に含まれている。

 このようにADO.NET Data ServicesはRESTスタイルをベースとしており、それによって各種のスクリプト言語からのアクセスが容易なものとなっている(一方、SOAPベースのWebサービスは静的型付け言語を対象とし、WSDLからのスケルトン・コード自動生成によるクライアント開発を念頭に置いているため、動的なスクリプト言語からのアクセスには手間がかかることが多い)。

■ADO.NET Data Servicesのアーキテクチャ

 ADO.NET Data Servicesは以下の図のようなアーキテクチャを持っている。


図1 ADO.NET Data Servicesアーキテクチャ

 図の上側がクライアント側であるが、前述のとおり、この部分とはRESTスタイルのHTTP通信により、Atom/JSON形式でデータをやりとりする。ここで注目していただきたいのは図の下側である。

 図からも読み取れるとおり、ADO.NET Data Servicesはそれ自体がデータベースにアクセスするための機能を持っているわけではなく、実際のデータベースへの接続/操作はバックエンドで行う。ここには、Entity Data ModelないしはCLRベースのデータモデルを使用可能である(Entity Data Modelについては、「.NETの新データアクセス・テクノロジ『ADO.NET Entity Framework』」を参照のこと)。

 CLRベースのデータモデルでは、データの参照に使用するIQueryableインターフェイス、データの更新に使用するIUpdatableインターフェイスにより、LINQ to SQLやほかのオブジェクトへのアクセスを実現できる。なお、LINQ to SQLはIQueryableインターフェイスしか実装していないため、別途IUpdatableインターフェイスを実装するのでなければ、データ更新は行えず、参照のみの利用となる。

 CLRベースのデータモデルを用いるならば、データベース以外の配列やオブジェクトなどを対象とすることもできるが、本記事ではADO.NET Data Servicesとの組み合わせにおいて、より一般的であるEntity Data Model(ADO.NET Entity Framework)を使って説明を行う。

■Atom/JSON対応

 ADO.NET Data Servicesはクライアントとの通信において、Atom/JSON両方の形式に対応している。両形式の切り替えはHTTPリクエストのAcceptヘッダで行う。デフォルトはAtom形式であり、Acceptヘッダに「application/json」が指定された場合にはJSON形式となる。

■URIによるリソース指定方法

 前述のとおり、ADO.NET Data ServicesはRESTスタイルのWebサービスであり、URIを使ってリソースを特定する。以下にリソースの指定についてのいくつかのパターンを示す。なお、URI内のサーバの後に指定している「/database.svc」は、後述のWebサービスのエントリ・ポイントを示している。

URI URIが示すリソース
http://server/database.svc/Orders Ordersレコード一覧
http://server/database.svc/Orders(10248) Ordersレコードの主キーが10248であるレコード
http://server/database.svc/Customers("VINET") 主キーが文字列の場合の指定方法
http://server/database.svc/Orders(10248)/OrderDate 指定したレコードのフィールドの値
http://server/database.svc/Orders(10248)/Customers ネストしたテーブル
http://server/database.svc/Orders(10248)/Customers("VINET")/CompanyName ネストしたテーブルのフィールド
http://server/database.svc/Orders?$orderby=ShipCountry ShipCountryフィールドでソートしたレコード
http://server/database.svc/Orders?$filter=(OrderID)lt(10250) OrderIDが10250未満のレコード(「lt」は未満を表すキーワード)
http://server/database.svc/Orders?$filter=OrderID%20lt%2010250 上と同じパターン。カッコの代わりに半角スペース(%20はURLエンコードで半角スペースを表す)でもよい
http://server/database.svc/Orders?$top=10 先頭10レコード
http://server/database.svc/Orders?$top=10&$skip=100 101レコード目から10レコード
表3 ADO.NET Data Servicesでのリソース指定方法

 以上のように、ADO.NET Data Servicesを使うことで、レコード一覧取得や特定のレコードの取得だけでなく、ソート、フィルタ、ページングなどのさまざまな機能を使った取得を、特別なコーディングなしで行うことができる。

■アクセス権

 ADO.NET Data Servicesは、初期状態では指定されたデータモデルのいずれのリソースについても、読み書きの一切が無効化された状態(ロックアウト状態)であり、特定のリソースについて明示的に読み書きを許可して初めて使用可能となる(許可するためのコードについては後述)。

 このように、セキュリティのデフォルト状態がロックアウトであることは、意図しないリソースが読み書き可能な状態になるのを防ぐという点で有益である。リソースのアクセスについては、単一/一覧レコードの取得許可/禁止、挿入、更新、削除、マージの許可/禁止といった条件を指定可能である。

■ビジネスロジックの追加

 ADO.NET Data Servicesでは、データベースのリソースを直接公開するだけでなく、ビジネスロジックを伴うリソース取得を実装することができる。その際は、データを参照するためのIQueryableインターフェイスを返すメソッドとして実装を行う。

 例えば以下のコードは、文字列配列を返すビジネスロジックを公開する例である。

[WebGet]
public IEnumerable<string> CustomObjects()
{
  return new string[] { "test1", "test" };
}
<WebGet>
Public Function CustomObjects() As IEnumerable(Of String)

  Return New String() {"test1", "test"}

End Function
リスト1 文字列配列を返すビジネスロジックの例(上:C#、下:VB)

■インターセプタの実装

 前述のアクセス権指定以外にも、「インターセプタ」を実装することで、リソース内容を横取り(=インターセプト)し、クライアントへの出力前にデータのフィルタ処理などを行うことができる。

 例えば以下のコードは、Employeesテーブルを取得する際にインターセプトを行い、TitleOfCourtesyフィールドが「Mr.」であるレコードだけを抽出するようフィルタを行う例である。

[QueryInterceptor("Employees")]
public Expression<Func<Employees,bool>> OnQueryCustomers()
{
  return o => o.TitleOfCourtesy == "Mr.";
}
<QueryInterceptor("Employees")>
Public Function OnQueryCustomers() As Expression(Of Func(Of Employees, Boolean))

  OnQueryCustomers = _
    Function(o As Employees) o.TitleOfCourtesy = "Mr."

End Function
リスト2 フィルタを行うインターセプタの例(上:C#、下:VB)

対応するクライアント

 ADO.NET Data ServicesはAtom/JSONという標準化されたフォーマットに基づいてクライアントとの通信を行うため、HTTP通信とXMLもしくはJSONに対応可能であれば、どんな環境からでもサービスを利用できる(この中には各種のスクリプト言語も該当するだろう)。さらに、以下のクライアントについては、ADO.NET Data Servicesを直接的にアクセスできるライブラリが用意されている。

■.NETアプリケーション全般

 System.Data.Services.Clientアセンブリを使うことで、ASP.NET/Windowsフォーム/WPF(Windows Presentation Foundation)などの.NETプログラミングにおいて、ADO.NET Data ServicesによるWebサービスを、Atom/JSONなどを意識することなく直接呼び出して使用することができる。また、LINQのデータソースとしてシームレスに使用可能である。

■Silverlight 2

 Silverlight 2 SDKにはADO.NET Data Servicesクライアント・ライブラリが含まれている。このライブラリを使うことで、ADO.NET Data ServicesによるWebサービスを、Atom/JSONなどを意識することなく、直接呼び出して使用することができる。.NETの場合と同様に、LINQのデータソースとしても用いることができる。

■ASP.NET AJAX

 ASP.NET AJAX向けには、「AJAX Client Library for ADO.NET Data Services」が用意されている。このライブラリを使うことで、JavaScriptからADO.NET Data Servicesを直接呼び出して使用できる。なお、AJAX Client Library for ADO.NET Data Servicesは純粋なJavaScriptのライブラリであるため、Microsoft AJAX Libraryと組み合わせることで、J2EEやRuby on RailsなどのASP.NET以外の環境でも使用できる。


 INDEX
  Visual Studio 2008 SP1新機能解説(1)
  DBアプリをコーディングレスで構築する「ASP.NET Dynamic Data」
    1.Dynamic Dataアプリケーションの基本
    2.データ・モデルの作成/Global.asaxの編集
    3.メタデータ編集によるDynamic Dataアプリケーションのカスタマイズ
    4.自作ユーザー・コントロールの利用/ページ・テンプレートのカスタマイズ
 
  Visual Studio 2008 SP1新機能解説(2)
  .NETの新データアクセス・テクノロジ「ADO.NET Entity Framework」
    1.ADO.NET Entity Framework概要
    2.Entity Data Model(EDM)の作成と利用
    3.EDMに対するクエリの利用方法(Entity SQL)
    4.EDMに対するクエリの利用方法(Object Services/LINQ to Entities)
 
  Visual Studio 2008 SP1新機能解説(3)
  RESTスタイルのWebサービスを手軽に公開する「ADO.NET Data Services」
  1.ADO.NET Data Services概要/対応するクライアント
    2.サンプル − ADO.NET Data Servicesの公開
    3.ASP.NET AJAX環境のデータを取得/追加する


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間