- PR -

Web サービスにおけるDBの更新処理

投稿者投稿内容
Micky
大ベテラン
会議室デビュー日: 2002/09/04
投稿数: 137
投稿日時: 2003-11-26 15:12
Mickyでございます。
いつも参考にさせていただいております。

XML Webサービスを使用した(実際にはノータッチデプロイメント
との組み合わせで…)DBの更新方法についてです。
みなさんはどういった方法(排他制御を含めて)を使っているのか
お伺いしてみたくなりました。
実際、スタンダード的な手法はあるのかな?と思いまして…

排他に関してはSQL Serverなので自動で制御されると思っておりますが、
以前のスレッドで紹介されていた
http://ukamen.hp.infoseek.co.jp/Programming3/Conflict/index.htm
の記事も参考にさせて頂きましたが、説明での制御方法が
ソース上でどの部分にあたるのかよくわかりませんでした

自分ではXML Webサービスとの架け橋はDataSetと認識しております。
(DataRow等はパラメータや戻り値としては使用できない)
それを前提にして…

1:UI側で、最初に取得したDataSetから該当するTableSetに対して、
Insert、Delete、Updateと必要な変更は全て行ってから
DataSetをパラメータとして渡し、Webサービス側メソッド内の
DataAdapterのUpdateメソッドにより一気にDBへの更新を行う。

※DataAdapterのデフォルト的使い方?但し複数の行に不整合が発生
する可能性があるので、このあたりをどのように解決するか?

2:UI側で、最初に取得したDataSetから該当するTableSetに対して、
Insert、Delete、Updateの対象となったレコードの変更終了時に
DataSetをパラメータとして渡し、Webサービス側メソッド内の
DataAdapterのUpdateメソッドにより該当レコードのみDBへの更新を行う。

※DataSetを渡してUpdateしているが実際に変更されるレコードは
1レコードなのでパフォーマンスへの影響は?

3:2と同様に1レコードずつ変更するが、DataAdapterのUpdateではなく
パラメータとして全カラムの情報を渡し、Webサービス側で
それぞれ別々に用意した更新メソッドを呼び出す

※パラメータの数が多くなってしまう。処理ごとにメソッドが必要

4:上記以外


もちろん、ケースバイケースでしょうが、ユーザーマスタメンテナンス
のような単純なケースを想定しております。

参考までにご意見をお聞かせいただければ幸いです。
よろしくお願いします。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-11-26 16:31
 1で行おうとしています。現行バージョンはMickyさんと同様、ノータッチ+Webサービスです。現行は、全く考慮していません!!(ぉぃ

 で、次バージョンですが、テーブルに「更新日時」カラムを追加しました。これを比較することで、「DataSetに引っ張ってから更新されたかどうか」をチェックしようと思います。

 SQL Serverでできるのかどうかわかりませんが、Oracleでは、CASE式で判別できるので、違っていればそのもので書き換えようかと。
UPDATE table1 SET column1 = (CASE WHEN UPD = ?UpdateTime THEN ?NewValue ELSE column1 END), UPD = (CASE WHEN UPD = ?UpdateTime THEN CURRENT_DATE ELSE UPD END) WHERE ID = ?id

 問題は、書き換えが起こらなくても「書き換えた」と判別される(RowStateが変わる)ところ・・・
小野@どっとねっとふぁん
ぬし
会議室デビュー日: 2001/10/30
投稿数: 402
投稿日時: 2003-11-26 16:50
1のような方法で更新するときに、エラー(一度データを取り出した後
更新されたもの等)となったデータだけを取り出して返すやり方がMSDNの
本国のサイトにのっていた記憶があります。

#Webサービスの事例ではなかったかも。
 でもDataSetの扱いでこれができるんだったら応用ききますよね。

ただ、どこに書いてあったか覚えてないんだな、これが(^^;
Micky
大ベテラン
会議室デビュー日: 2002/09/04
投稿数: 137
投稿日時: 2003-11-28 16:22
Mickyでございます。

Jittaさん、小野@EACさんこんにちは!
書き込みありがとうございました。

やっぱり「1」が王道なんですかね
この辺りの例って、なんかないですよねぇ〜
でも、正直言いますともちょっと「俺はこうしてる」
みたいな書き込みもあるかと思っていました。

実際のところ「Webサービス&ノータッチデプロイメント」で
Goサインがでるプロジェクトもまだまだ少ないのかな?
とも思っております。

※私情ですが…
私的には御大と思っている(勝手に)お二方に書き込みいただいて
ちょっと嬉しかったりしてます・・・(^^)
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-11-28 17:19
 そういえば、変更のあった行だけ取り出す、というメソッドがあったと思うので、それを使えば「返送」のデータトラフィックは減らせますね。


 で、実際ノータッチで1つ作った感想ですが、Windows2000以降のみで構成されたネットワークでないときついです。98, Me, NTでは、ダウンロードキャッシュの場所がない(NTは勘違いかもしれない)ので、毎回ダウンロードします。これらのOSではブロードバンドが生かせる設定になっていないので、特に遅い。また、ウェブサービスとのやり取りも、文字列にシリアライズされているので、遅い。セキュリティの関係がまたややこしくて、アクティブディレクトリなら一括配信できるのですが、ドメイン運用なら各PCに配布しなければならないので、これが面倒。

 まだまだ98, Me, NTが使われている現状では、インフラがネックかなぁ。
Os_
ベテラン
会議室デビュー日: 2003/04/16
投稿数: 77
投稿日時: 2003-11-29 10:43
おさです。
私も現在SQL Server+Webサービスのシステムを手がけていますが、
1も方法を用いております。
また、返送するデータは「DataSet.GetChanges」メソッドを使って更新のみのDataSetを抽出して行っています。Jittaさんが書かれているのはこの事だと思います。

さて、排他制御の件ですが、私の例は排他ではなくマルチで更新可能にする為、上書き防止として以下の方法を用いています。
・SQL Serverの主キー列のID番号とtimestampの組合せで取得した元データの更新を判断
・元データのtimestampと一致したらUpdateを実施
・元データのtimestampが更新されていたら、更新された元データを読み取り返す。
・クライアント上の更新データとマージし、データ取得後の更新部分をユーザーに明示する。
・ユーザーが更新内容を確認&編集後に再度更新する。
尚、データのマージにはDataSet.Merge()メソッドが利用できるかと思います。
要望と違うかな?
Micky
大ベテラン
会議室デビュー日: 2002/09/04
投稿数: 137
投稿日時: 2003-12-02 14:54
Mickyです。

Jittaさん、おささん、引き続きの情報提供ありがとうございました。

実際に作ってみた所で更なる問題点や、有用な情報(こっちだといいのですが…)
を書き込みできる様にがんばってみたいと思います(^^)
Micky
大ベテラン
会議室デビュー日: 2002/09/04
投稿数: 137
投稿日時: 2004-01-09 14:22
Mickyでございます。
いつもお世話になっております。

えっと、みなさまからご助言頂いた後もぽつぽつと調べたり、
いろいろ試したりしていたのですが、
現在の所、WebServiceのサーバー側でUpdateメソッドによる
複数のレコードの一括更新はどうも親和性がよくないのでは?
と言う方向に傾きつつあります。

と言うのは最初にも書いたのですが、更新された複数のレコードで
エラーが発生する可能性があり、
その対応処理についてよい方法が見つからないからです。


対象となる更新済みDataSetのUpdateメソッドを使用するとUpdateの結果をDataSetの
当該DataRowに設定してくれますよね。
これって、成功したレコードと失敗したレコードが混在してるわけです。
通常のC/Sシステムや、Webアプリならこの情報(DataSetそのもの)を
そのまま使用できるし、なおかつWinコントロールのDataGridなら
エラーマークも表示してくれます。

しかし、XMLでのDataSetではこれらの情報はなくなってしまうので
更新の成功/失敗の情報を更新レコード分、付加してやらなければ
ならない事になります。
更にこの情報から「追加、変更、削除」それぞれの処理に対応する
エラー処理、元々持っていたDataSetとの整合性を取る事等、
処理が煩雑になるような気がしています。

それよりは、更新対象となる1レコードのみ処理した方が
確実な気がするのですがいかがでしょうか?
以下が基本的な流れですが、
「いやいや、そこは勘違いしてる」
「その考えはおかしいんじゃん?」
「考慮すべきことが抜けている」
等々ご意見いただけたらありがたいと思います。

・WebServiceよりDataSetを取得
・ノータッチデプロイメントアプリで表示
・該当データを更新(編集後、更新ボタン)※「追加、削除」も流れは同じ
・GetChangesメソッドで、更新されたレコードを抽出
(更新された1レコードのみ抽出されるはず)
・WebServiceのUpdate用メソッドへ抽出レコード(DataSet)を渡す
・渡されたDataSetのUpdateメソッドによりDBの更新(あくまで対象は1レコード)
・処理結果を返す
・ノータッチ側では更新の成功/失敗により該当レコードに対しての処理を行う
(すでに更新されているなら、該当レコードを再度読み込んで編集し直す等…)

※一番の問題はやはりレスポンスでしょうか…

スキルアップ/キャリアアップ(JOB@IT)