1

ASP.NET MVC アプリケーションの対応するコントローラー内でtry-catchブロック ( catch/handle を目指して) を使用してリポジトリへの呼び出しをラップする必要がありますか、それともリポジトリ実装内で行う必要がありますか?StaleObjectStateException

また、例外をどのように処理すればよいか、ユーザーに通知してください。私が理解している限り、ロールバックは意図されていませんか?

ありがとう!

4

2 に答える 2

3

問題は別の問題に要約されます: エンティティの同時変更をどこでどのように処理するか? つまり、ユーザー A とユーザー B が同じレコードを編集し、後でレコードを保存したユーザー (ユーザー B) が StaleObjectStateException を取得すると、彼が編集したバージョンが現在古くなっているためです。

ここにいくつかのアイデアがあります:

  1. たとえば、DB からレコードの現在のバージョンを取得し、ユーザー B のバージョンの状態全体をそれに適用するなど、力ずくでユーザー B のバージョンを強制的に「正しい」バージョンにします。これは、ユーザー A が「電子メール アドレス」フィールドなどを変更し、ユーザー B が「ユーザー名」フィールドを変更した場合に問題になります。このアプローチでは、ユーザー A が行ったことはすべてなくなります。このアプローチでは、StaleObjectStateException をキャッチし、リポジトリ内のすべてを修正します。

  2. 「スマートな」アプローチ: アプローチ 1 と同様に、リポジトリ内ですべてが修正されます (つまり、StaleObjectStateException を完全にキャッチして処理します) が、ドメインの知識を使用して、ユーザー B が行った変更の一部のみを選択的に適用します。たとえば、ユーザー A が電子メール アドレスを変更し、ユーザー B がユーザー名を変更した場合、これらの変更は互いに除外されないため、リポジトリは電子メール アドレスのみを更新できます。これは、相互に直接依存しないレコードの 2 つの側面が同時に変更された場合にうまく機能します。このソリューションの実装は、どの程度「スマート」になりたいかによって、かなり複雑になる可能性があります。

  3. リポジトリ内での同時変更を拒否します。この場合、StaleObjectStateException が発生した場合、リポジトリはレコードを保存できなかったことを報告する必要があります。実際には例外が発生する可能性がありますが、NHibernate をコントローラーなどにリークしています。代わりに、ドメインにとって意味のあるより有用な詳細を使用して、独自の例外をスローすることができます。この状況では、コントローラーはその例外をキャッチするのに適した場所です。次に、何をすべきかについてさまざまなオプションがあります。たとえば、次のようになります。

    • 別のユーザーによる同時変更のためにレコードを保存できなかったことをユーザーに通知し、すべての変更を破棄して、すべてを最初から行うように強制します。もちろん、これはユーザーにとって苦痛であり、これが実際にめったに発生しない場合にのみ実行する必要があります。
    • 問題についてユーザーに通知し、変更を強制するか最初からやり直すなど、何をすべきかをユーザーに決定させます。

これはあなたの質問を超えていますが、これがまだあなたに役立つことを願っています.

于 2012-02-24T18:41:04.773 に答える
2

DIを適切に使用している場合、この種の例外管理をコントローラーに配置すると、懸念の分離が壊れます。

コントローラーはプレゼンテーション層に属し、プレゼンテーション層はデータ ストレージに何を使用しているかを認識せず、StaleObjectStateException は NHibernate のものです。

于 2012-02-24T14:40:35.053 に答える