アプリケーションのサーバー側は、データベースからデータをロードし、それをサーバーに返したり、クライアントから変更のリストを受け取り、それをデータベースに適用する Web サービスで構成されます。
サーバー側は、汎用のハンドラクラス(ashx)、Web サービス(asmx)、または Silverlight 対応の WCF サービス(SVC)として実装できます。このサンプルではどれでも実装できますが、ここでは標準的な Web サービスを選択します。
サービスを作成するには、次の手順に従います。
[追加]ボタンをクリックすると、新しく作成された DataService.asmx.cs(または DataService.asmx.vb)ファイルが Visual Studio で開かれます。このファイルには、1つの HelloWorld メソッドのみがあります。
このファイルを次のように編集します。
コードのコピー
|
|
---|---|
using System.IO; using System.Data; |
コードのコピー
|
|
---|---|
[System.Web.Script.Services.ScriptService] |
コードのコピー
|
|
---|---|
[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 などのデータ圧縮ライブラリを使ってストリームを圧縮し、ストリームのサイズを大幅に縮小してからクライアントに返すこともできます。ただし、ここでは、サンプルをできるだけ単純にするため、あえて圧縮しませんでした。
コードのコピー
|
|
---|---|
[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 を返します。エラーが発生した場合は、例外について説明したメッセージを返します。
コードのコピー
|
|
---|---|
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 メソッドを呼び出して、変更をデータベースに書き込みます。
コードのコピー
|
|
---|---|
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 を呼び出し元に返します。