3

私はc#とasp.netを使用して自分のWebサイト用のフォーラムシステムを作成しています。データアクセス用には型付きデータセットを使用し、UI用にはmvpパターンを使用しています。私のデータベースには、データセットに追加されたストアドプロシージャがあります。問題は、データセットで[楽観的同時実行性を使用する]チェックボックスを選択できなかったため、自分で楽観的同時実行性を実装する必要があったことです。テーブルにタイムスタンプ列が追加されましたが、ユーザーごとにこの値を保存する際に問題が発生しました。では、タイムスタンプ値を保存するために使用するのに安全でコストのかからない状態管理アプローチはどれですか?

値を格納するためにセッションを使用するのが最善だと思いましたが、ユーザーの数が増えるとメモリリソースに問題が発生しますが、メモリの代わりにSQLサーバーを使用するようにセッションを設定できますが、それがどれほど遅くなるかはわかりませんだから私はそれについて決めることができません。

どんな助けでも大歓迎です!

編集1:はい。行の最後の変更を追跡して、ユーザーが持っているものと一致するかどうかを確認したいと思います。しかし、ユーザーのタイムスタンプ値をどこに保存するかわかりません。

4

1 に答える 1

6

フォーラムタイプのアプリケーションであるためにタイムスタンプ/行バージョンを使用できない場合は、投稿の作成/変更された日付/時刻を追跡すると思いますか?もしそうなら、これは簡単に確認できます。

更新しました

SQLServerモード

SQL Serverモードの使用例は通常、Webサーバーファームであるため、ASP.NETセッション状態は複数のサーバーにわたって持続します。これにより、Webサーバーが使用できなくなっても、別のサーバーが使用可能である限りセッションを正常に続行できるため、少し堅牢になります。SQL Serverモードは、同じサーバーのメモリ内(アウトプロセス)または同じプロセス(インプロセス)ではなくデータベースにクエリを実行しているためにリソースが激しく競合しない限り、ローカルほど高速ではありません。

MVCパターンとセッション状態

アプリケーションでWebFormViewEngineを使用している場合は、状態を使用できますが、MVCパターンのプライマリテナントはステートレスになります。

行バージョン/タイムスタンプをステートレスで追跡する方法

ステートレスな方法で行バージョンを追跡するには、それをクライアントに返す必要があるため、コントローラーアクションへのコールバックが行われると、それが提供されます。

<%= Html.HiddenFor(Model.VersionId) %>

これにより、結果のHTMLフォームに非表示フィールドが表示されます。

<input type="hidden" name="VersionId">1</input> 

安全ですか?

これを一時的にクライアントに保存しても安全ですか。Webアプリケーションに対する攻撃の一部として誰かが値を変更する可能性があることを十分に理解しています。

私たちが知っていることを分析しましょう:

  • 同じテーブルで同じ行バージョンが重複しないように、手動でインクリメントすることはお勧めしません。
  • レコードごとではなく、テーブルの挿入/更新ごとに順番にインクリメントされます。つまり、レコードAにはバージョン1が含まれる可能性があります。レコードBにはバージョン2が含まれる可能性があります。レコードAを次に更新すると、2ではなく3になります。http://msdn.microsoft.com/en-us/library/ms182776.aspxを参照してください。

これに基づいて、rowversionを使用するようにアプリケーションを作成し、rowversionを使用して、現在のリクエストの更新間でレコードが変更されたかどうかを判断します。常にDBにrowversionを内部的にインクリメントさせます。したがって、ストアード・プロシージャーは比較のために値を受け入れますが、テーブル/ビューに値を挿入または更新しません。

では、誰かが行バージョンを操作しようとした場合に、行バージョンで発生する可能性のあるケースは何でしょうか。

  1. クライアントが提供するrowversionは、DBのrowversionよりも小さくなります。
  2. クライアントが提供するrowversionは、DBのrowversionと同じです。
  3. クライアントが提供するrowversionは、DBのrowversionよりも大きくなります。

それを分解してみましょう。

では、クライアントの行バージョンがDBよりも小さい場合、それはどういう意味ですか?

クライアントは、データを編集するときに古いコピーを使用しました。これは、データがDBから最後に読み取られてから変更されたためです。これを処理するには、次のいずれかを実行できます。

A.エラーを出し、データをリロードして、変更を再送信してもらいます。

B.変更を現在のコピーにマージし、再送信する前に確認を求めます。

C.DB内の既存のコピーを上書きします。それは可能ですが、同時に複数の変更を処理するために同時実行モデルを実装したため、最適ではない可能性があります。これにより、AとBが残ります。

もう1つのオプションは、クライアントがrowversionの値を実際のDB値よりも小さくなるように変更したことです。この場合、rowversionの値を変更したとしても、それは重要ですか?そうではなく、他のユーザーと同時に変更があった場合と同じように処理することをお勧めします。オプションAとBを再度返します。

では、クライアントの行バージョンがDBと等しい場合、それはどういう意味ですか?

クライアントは期待したバージョンを編集していて、送信ボタンを押しています。これを処理するには、次のいずれかを実行できます。

A.変更を受け入れて続行します。

B.変更を拒否し、フィードバックメッセージを提供します。データベースにデータを取り込むことが全体として重要であるため、これを実行することはほとんどありません。

もう1つのオプションは、クライアントがrowversionの値を私たちが期待していた正確なバージョンに変更したか、すべての送信に対して行うように私たちが期待していた行バージョンをクライアントに伝えたため、おそらくまったく変更しなかったことです。ただし、行バージョンを変更し、更新を投稿したクライアントが同時に存在し、これが最後に送信される更新である場合。

このケースは、AまたはBの前と同じように処理できます。残念ながら、期待どおりだったため、実際に行バージョンが変更されたことを知る方法はありません。ただし、レコードを更新する許可はすでに付与されています。レコードを更新する必要がない場合は、更新する権限がないはずです。

とはいえ、DBに書き込む前に、すべての入力の健全性を検証し、サニタイズします。

これが適切でない場合は、アプリケーションにコンテンツのバージョン管理または承認プロセスを実装して、各レコードを更新する前に制御できるようにするか、前のバージョンにロールバックできるようにする必要があります。

では、クライアントの行バージョンがDBよりも大きい場合、これはどういう意味ですか?

オプションは、rowversionがDBよりも小さい場合とまったく同じです。予期されていなかったので、AまたはBのどちらかです。Cは目的を果たさないため、オプションではない可能性があります。

結論

それで、フォーラムのWebアプリケーションにとって安全ですか?入力を検証する必要がありますが、rowversionが予想と異なる場合は、これを解決する方法があります。

最後の最後の手段として、行バージョンをエンコードまたは暗号化して、シーケンスが簡単に推測されないようにすることもできます。

だから私の意見ではそうですが、それは最終的にはあなたの呼びかけです。

于 2011-09-13T22:42:55.367 に答える