CodeZine(コードジン)

特集ページ一覧

ADO.NET Data ServicesでRESTfulなサービスを実現する

ASP.NET 3.5 Extensions + ASP.NET MVCフレームワーク(4)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2009/02/04 14:00
目次

ADO.NET Data Servicesを利用したWebサイトの作成

 Data Servicesをホストするプロジェクトを作成し、動作も確認しました。続いてData Servicesを利用するクライアントプロジェクトを作成します。

プロジェクトの作成

 ホストプロジェクトにクライアントプロジェクトを追加します。メニューの[ファイル]-[追加]-[新しいプロジェクト]と選択し、Webプロジェクトを作成します(サンプルではSampleAstoriaClientと名前設定)。

 展開されたDefault.aspxページ上に、以下の要領でコントロールを追加してください(図9)。

図9 配置完了後のフォーム デザイナ画面
図9 配置完了後のフォーム デザイナ画面
Default.aspxページ上に配置するコントロール
コントロール 個数 プロパティ設定
GridView 1個 特になし
Button 3個 それぞれテキストに「挿入」「更新」「削除」と設定

 ボタンコントロールはそれぞれクリックイベントを追加します。以上でフォームの設定は完了です。また、ポートの設定はホストプロジェクト同様の手順で''51000''と設定しておきましょう(分かりやすくするためであってそれ以上の意味はありません)。

.NETのクラスからADO.NET Data Servicesにアクセスする

 フォームの準備もできたので、最初は.NETアプリケーションからData Servicesにアクセスする方法について解説します。

.NETクライアント クラスの作成

 さて、下準備が済んだ所でホストプロジェクトのData Servicesにアクセスするための中間クラスを作成します。本来はData Servicesクラスをクライアントで利用するためのSystem.Data.Services.Clientクラスを利用して、手書きでData Servicesから返されるデータをクライアント上で、オブジェクトとして操作するためのクラスを作成します。

 この作業はかなり煩雑です。しかし、VS2008 SP1のSDKツール''DataSvcUtil.exeツール''を利用すると、[Visual Studio 2008 コマンド プロンプト]上でコマンドを記述するだけで、EDMのデザイナクラス(サンプルで言うと、Pubs.Designer.cs)とほぼ同一の内容が記述されたパーシャルクラスを含んだクラスを自動生成します。EDMのデザイナクラスとの違いはパーシャルクラスである点と、利用するコンテキストが直接EDMを操作するコンテキストか、クライアントから操作するコンテキストかの違いです。尚、自動生成されるクラスはAtomPub形式を使用しています。

 それでは、作成する手順を解説します。

 Visual Studio 2008 コマンドプロンプトを管理者実行して以下のコマンドを実行します。

> cd C:\Windows\Microsoft.NET\Framework\v3.5 > DataSvcUtil.exe /out:c:\PubsTitles.cs /uri:http://localhost:50000/PubsAstoria.svc

 今回利用したパラメータは以下の通りです。なお、既定で生成される言語はC#となっています。VBで生成したい場合は、ファイル名.vbの他に、/language:VBの設定が必要になります。

DataSvcUtil.exeツールのオプション
パラメータ 概要
/out:<ファイル名> クラスの出力先(クラス名の設定含む) 
/uri:<URI> Data ServicesのURI
/language:VB VBでクラスを生成

 生成されたクラスは対象となるData ServicesのEDM次第ですが、サンプルでは以下のようなクラスが生成されます。長くなるので一部抜粋させて頂きます。

// pubsModel名前空間の作成
namespace pubsModel
{
    
    /// <summary>
    /// スキーマの pubsEntities にはコメントがありません。
    /// </summary>
    // pubsEntitiesパーシャルクラスにグローバル名前空間を利用して設定
    public partial class pubsEntities : global::System.Data.Services.Client.DataServiceContext
    {
        /// <summary>
        /// 新しい pubsEntities オブジェクトを初期化します。
        /// </summary>
        // pubsEntitiesオブジェクトのパラメータにグローバル名前空間を利用して設定
        public pubsEntities(global::System.Uri serviceRoot) : 
                base(serviceRoot)
        {
            this.OnContextCreated();
        }
        partial void OnContextCreated();
        /// <summary>
        /// スキーマの publishers にはコメントがありません。
        /// </summary>
        // グローバル名前空間を利用してDataServiceQuery<publishers>を設定
        public global::System.Data.Services.Client.DataServiceQuery<publishers> publishers
        {
            get
            {
                if ((this._publishers == null))
                {
                    // DataServicesからpublishersエンティティオブジェクトの取得
                    this._publishers = base.CreateQuery<publishers>("publishers");
                }
                return this._publishers;
            }
        }

    // 以下、残りのtitlesエンティティの各項目の記述のため中略
    }
}

 ''global::''は、グローバル名前空間(最優先される名前空間)を参照し、現在のエイリアスを参照しません。つまり、上記の例で言うと、pubsEntitiesパーシャルクラスはパラメータに''System.Uri serviceRoot''を適用しています。

 DataServiceContextクラスは、Data Servicesの実行時のコンテキストを表すクラスで、機能的には持ち得ないData Servicesの状態(ステート)を保持するための機能を持つクラスです。今回は項目の追加という状態を保持しています。

 DataServiceQueryクラスは、Data Servicesへの特定のHTTPクエリを表す抽象クラスです。このクラスのオブジェクト インスタンスは、DataServiceContextクラスのCreateQuery(T) メソッドを使用して作成します。CreateQuery(T) メソッドは指定されたデータについてのData Servicesのクエリを作成します。

 簡単にまとめると、Data Servicesが利用しているEDMの名前空間を利用し、Data Servicesは経由するものの各エンティティへのアクセスが可能なオブジェクトをDataServiceContextクラスとDataServiceQueryクラスを利用して作成し、クライアント側に提供するクラスです。

LINQ to ADO.NET Data Servicesを使ってADO.NET Data Servicesにクエリを行う

 DataSvcUtil.exeツールを使って生成されたクラス(以下、クライアント ライブラリ)はLINQを使ってData Servicesにクエリを行うこともできます。.NETアプリケーションからアクセスする場合は、クライアント ライブラリを使いLINQ to ADO.NET Data Servicesを利用することが多くなるでしょう。クラスは、URIにLINQのステートメントをマッピングして処理を行います。

 最初は、ページロード時にGridViewコントロールにtitlesテーブルのデータを全て表示させてみましょう。最初に参照設定に[System.Data.Services.Client]名前空間を追加します。続いてWhereステートメントなどを利用していないので非常にシンプルなコードとなります。実行結果は図10になります。

図10 実行直後の画面
図10 実行直後の画面
// 既定の名前空間のほか以下の2つの名前空間を追加
using System.Data.Services.Client;
using pubsModel;

        protected void Page_Load(object sender, EventArgs e)
        {
            // pubsEntitiesオブジェクトにData Servicesのアドレスを設定して生成
            pubsEntities edm = new pubsEntities(new Uri("http://localhost:50000/PubsAstoria.svc"));

            // titlesテーブルをすべて選択
            var pubas = from p in edm.titles
                        select p;

            // GridView1にデータをバインディング
            GridView1.DataSource = pubas;
            GridView1.DataBind();
        }

 pubsModel名前空間はクライアント ライブラリを参照するために指定しています。クライアント ライブラリでは、ホストプロジェクトのEDMで定義されたPubsエンティティ型のオブジェクトであるpubsEntitiesオブジェクトにサービスがホストされているURIを初期値として設定して生成します。これにより、LINQ to ADO.NET Data Sevicesを実行するためのオブジェクトの準備ができます。その後、titlesテーブルのデータを全て抽出するLINQを行い、その結果をGridView1にバインディングして表示しています。

 続いて、配置した3つのボタンにそれぞれ挿入/更新/追加の処理を記述します。それぞれのクリックイベントに以下のコードを追加してください。

// 既定の名前空間のほか以下の2つの名前空間を追加
using System.Data.Services.Client;
using pubsModel;

        protected void Button1_Click(object sender, EventArgs e)
        {
            // 挿入
            // Data Service実行時コンテキストをData Servicesのアドレスを設定して生成
            DataServiceContext edm = new DataServiceContext(new Uri("http://localhost:50000/PubsAstoria.svc"));
            // Data Servicesのtitlesエンティティのインスタンス生成
            titles titlesEntity = new titles();

            DateTime dt = DateTime.Parse("2008/11/17");

            // titlesエンティティ・オブジェクトにnullを許容しない列に値を設定
            titlesEntity.pubdate = dt;
            titlesEntity.title = "Tamaki's Diary";
            titlesEntity.title_id = "N1107";
            titlesEntity.type = "Family";

            // 新しいオブジェクトとして
            // titlesエンティティに追加
            edm.AddObject("titles", titlesEntity);

            // 更新を反映
            edm.SaveChanges();

        }

        protected void Button2_Click(object sender, EventArgs e)
        {
            // 更新
            // pubsEntitiesオブジェクトにData Servicesのアドレスを設定して生成
            pubsEntities edm = new pubsEntities(new Uri("http://localhost:50000/PubsAstoria.svc"));
            // Data Servicesのtitlesエンティティのインスタンス生成
            titles titlesEntity = new titles();

            // titlesエンティティに対して主キーによる絞り込みを行い、1レコード返す
            titlesEntity = (from p in edm.titles
                          where p.title_id == "N1107"
                          select p).First();

            // 該当するエンティティの値を更新
            titlesEntity.title = "Tamaki's Photo Diary";
            edm.UpdateObject(titlesEntity);
            // 更新を反映
            edm.SaveChanges();

        }

        protected void Button3_Click(object sender, EventArgs e)
        {
            // 削除
            // pubsEntitiesオブジェクトにData Servicesのアドレスを設定して生成
            pubsEntities edm = new pubsEntities(new Uri("http://localhost:50000/PubsAstoria.svc"));
            // Data Servicesのtitlesエンティティのインスタンス生成
            titles titlesEntity = new titles();

            // titlesエンティティに対して主キーによる絞り込みを行い、1レコード返す            
            titlesEntity = (from p in edm.titles
                          where p.title_id == "N1107"
                          select p).First();

            // 該当するエンティティを削除
            edm.DeleteObject(titlesEntity);
            // 更新を反映
            edm.SaveChanges();
        }

 追加を行う時には、titlesエンティティを用意して、必要な項目の設定を行いAddObjectメソッドでtitlesEntityオブジェクトに追加するだけです。追加された要素をSaveChangesメソッドでEDMからデータテーブルに追加の情報を反映させています。注目すべき点は、追加する対象として、Data Servicesのアドレスを設定したDataServiceContextオブジェクトを生成している点です。今回は項目の追加という状態を保持しています。

 更新時には、LINQ to ADO.NET Data Servicesを使い、主キーによるtitlesQuery Builderメソッドの1つであるWhereメソッドを使い、更新対象となるtitlesEntityのレコードを取得します。更新を行いたいレコードの項目のプロパティを設定した後、SaveChangesメソッドで情報を反映させます。更新を行う対象として、Data Servicesのアドレスを設定したpubsEntitiesオブジェクトを生成しています。

 削除も更新と同じ要領で行います。更新との違いは抽出したレコードをDeleteObjectメソッドで削除しているという点だけです。

 LINQ to ADO.NET Data Servicesを使ってADO.NET Data Servicesにクエリを行う方法については以上です。途中にクライアント ライブラリを利用しているからではありますが、シームレスな連携を確認できたかと思います。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:ASP.NET 3.5 Extensions + ASP.NET MVCフレームワーク

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

  • WINGSプロジェクト ナオキ(ナオキ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5