Data for Silverlight
Web サービスの実装

アプリケーションのサーバー側は、データベースからデータをロードし、それをサーバーに返したり、クライアントから変更のリストを受け取り、それをデータベースに適用する Web サービスで構成されます。

サーバー側は、汎用のハンドラクラス(ashx)、Web サービス(asmx)、または Silverlight 対応の WCF サービス(SVC)として実装できます。このサンプルではどれでも実装できますが、ここでは標準的な Web サービスを選択します。

サービスを作成するには、次の手順に従います。

  1. MasterDetailWeb プロジェクトを右クリックします。
  2. [追加]→[新しい項目]を選択します。
  3. [新しい項目の追加]ダイアログボックスで、左ペインの[カテゴリ]リストから[Web]を選択します。
  4. 右ペインの[テンプレート]リストから[Web サービス]テンプレートを選択します。
  5. 新しいサービス名として「DataService.asmx」を指定します。
    ダイアログボックスは次の図のようになります。
  6. [追加]ボタンをクリックして、新しい Web サービスを作成します。

[追加]ボタンをクリックすると、新しく作成された DataService.asmx.cs(または DataService.asmx.vb)ファイルが Visual Studio で開かれます。このファイルには、1つの HelloWorld メソッドのみがあります。

このファイルを次のように編集します。

  1. ファイルの先頭にある文ブロックに、次の using 文を追加します。
    コードのコピー
    using System.IO;
    using System.Data;
    
  2. Silverlight からサービスを呼び出せるように、次の行のコメントを外します。
    コードのコピー
    [System.Web.Script.Services.ScriptService]
    
  3. Visual Studio が作成した HelloWorld メソッドを削除し、次のコードに置き換えます。
    コードのコピー
    [WebMethod]
    public byte[] GetData(string tables)
    {
      // 接続文字列を使って DataSet を作成します
      var ds = GetDataSet();
     
      // DataSet にデータをロードします
      ds.Fill(tables.Split(','));
     
      // ストリームに保存します
      var ms = new System.IO.MemoryStream();
      ds.WriteXml(ms, XmlWriteMode.WriteSchema);
     
      // ストリームデータを返します
      return ms.ToArray();
    }
    

    このメソッドでは、最初に SmartDataSet を作成し、そこに tables パラメータで指定されたテーブルのデータを挿入します。その後、WriteXml メソッドを使って DataSet をストリームに保存し、そのストリームをバイト配列に変換して、その結果を返します。

    このコードは、サーバー側で実行されることを思い出してください。C1.Zip などのデータ圧縮ライブラリを使ってストリームを圧縮し、ストリームのサイズを大幅に縮小してからクライアントに返すこともできます。ただし、ここでは、サンプルをできるだけ単純にするため、あえて圧縮しませんでした。

  4. 次に、以下のコードを使用して、変更をデータベースに保存し直すメソッドを追加します。
    コードのコピー
    [WebMethod]
    public string UpdateData(byte[] dtAdded, byte[] dtModified, byte[] dtDeleted)
    {
      try
      {
        UpdateData(dtAdded, DataRowState.Added);
        UpdateData(dtModified, DataRowState.Modified);
        UpdateData(dtDeleted, DataRowState.Deleted);
        return null;
      }
      catch (Exception x)
      {
        return x.Message;
      }
    }
    

    このメソッドは、3つのパラメータを受け取ります。各パラメータは、それぞれ異なるタイプの変更(レコードの追加、変更、削除)をデータベースに適用するために使用されます。このメソッドは、UpdateData ヘルパーメソッドを呼び出してそれぞれの変更セットを適用し、すべての変更が正しく適用された場合に null を返します。エラーが発生した場合は、例外について説明したメッセージを返します。

  5. UpdateData ヘルパーメソッドに以下のコードを追加します。
    コードのコピー
    void UpdateData(byte[] data, DataRowState state)
    {
      // 変更がない場合は何もしません
      if (data == null)
        return;
     
      // DataSet にデータをロードします
      var ds = GetDataSet();
      var ms = new MemoryStream(data);
      ds.ReadXml(ms);
      ds.AcceptChanges();
     
      // 変更された行の状態を更新します
      foreach (DataTable dt in ds.Tables)
      {
        foreach (DataRow dr in dt.Rows)
        {
          switch (state)
          {
            case DataRowState.Added:
              dr.SetAdded();
              break;
            case DataRowState.Modified:
              dr.SetModified();
              break;
            case DataRowState.Deleted:
              dr.Delete();
              break;
          }
        }
      }
     
      // データベースを更新します
      ds.Update();
    }
    

    このメソッドは、最初に SmartDataSet を作成し、そこにすべての変更をロードします。次に、各行の RowState プロパティを変更して、行に適用された変更のタイプ(追加、変更、削除)を識別します。最後に、SmartDataSet.Update メソッドを呼び出して、変更をデータベースに書き込みます。

  6. これで、サーバー側のコードは大部分準備できました。後は、SmartDataSet を作成して設定するメソッドを追加するだけです。この実装に以下のコードを追加します。
    コードのコピー
    SmartDataSet GetDataSet()
    {
      // mdb ファイルの物理的な場所を取得します
      string mdb = Path.Combine(
        Context.Request.PhysicalApplicationPath, @"App_Data\NWind.mdb");
     
      // このファイルの存在を確認します
      if (!File.Exists(mdb))
      {
        string msg = string.Format("Cannot find database file {0}.", mdb);
        throw new FileNotFoundException(msg);
      }
     
      // ファイルが読み取り専用でないことを確認します(ソースコントロールによって読み取り専用にされる場合があります)
      FileAttributes att = File.GetAttributes(mdb);
      if ((att & FileAttributes.ReadOnly) != 0)
      {
        att &= ~FileAttributes.ReadOnly;
        File.SetAttributes(mdb, att);
      }
     
      // SmartDataSet を作成および初期化します
      var dataSet = new SmartDataSet();
      dataSet.ConnectionString =
        "provider=microsoft.jet.oledb.4.0;data source=" + mdb;
      return dataSet;
    }
    

このメソッドは、最初にデータベースファイルを見つけ、その存在を確認し、そのファイルが読み取り専用でないことを確認します(読み取り専用である場合は、更新が失敗します)。その後、新しい SmartDataSet を作成し、ConnectionString プロパティを初期化して、新しく作成した SmartDataSet を呼び出し元に返します。

関連トピック

 

 


Copyright © GrapeCity inc. All rights reserved.