全て、
エラーが発生した場合、セッション オブジェクト (ISession またはその ISessionImplementor) から判断できますか? または、セッションでエラーが発生したときに呼び出される偶数ハンドラーをフックすることは可能ですか?
コードをtry/catchでラップし、セッションをすぐに破棄することにより、セッションを処理するパターンをよく知っています。ただし、私の場合は、現在のスコープで実行されている DAO に休止状態セッションを渡すセッション スコープに相当するものを実装しました。休止状態のセッションを提供すると、クライアント コードはそれを単に永続的な操作を実行するために使用します。セッション クリーンアップの責任をクライアントに負わせたくありません。これはセッション スコープの責任です。例を次に示します。
using (new SessionScope(SessionHelper.OpenSession()))
{
// do read/write etc.
// ex:
mydao.MakePersistent(someEntity); // <-- an error can occur here
} // implicit flush/clean up, BUT in order to do this correctly I have to know if the session in the scope has no errors!
ご覧のとおり、SessionScope は IDisposable を実装し、そこでフラッシュ、tx.Commit()、破棄などのセッションのファイナライズを行います。しかし、エラーが発生した場合、セッションをフラッシュできません!
回避策の 1 つは、生の休止状態セッションを提供するのではなく、セッション操作を実行するためのメソッドを備えたラッパー オブジェクトを提供することです。これにより、任意の操作を try/catch でラップし、エラーが発生した時期を知ることができます。あなたが私に尋ねると、それはばかげた回避策です。
もう 1 つのオプションは、すべての DAO がエラーが発生したことをセッション スコープに通知することです。つまり、すべての DAO メソッド (catch ブロック内) は、セッション スコープが定義されているかどうかを確認する必要があり、定義されている場合は、セッションの失敗に責任があります。 (scope.FailSession(session);) それははるかに優れていますが、すべての DAO で宗教的に行う必要があり、忘れると、エラーが発生したセッションで session.Flush() を呼び出して、セッション スコープが誤動作します。
Oskar B. のコメントのおかげで、ACID プロパティを持つ必要があるロジックや、持続性に関係のない例外のリスクがあるロジックには、トランザクション ベースのアプローチを使用する必要があります。修正されたソリューションは次のとおりです。
using (var txScope = new TransactionScope(SessionHelper.OpenSession()))
{
Customer cust = mydao.getCustomer();
Order order = mydao.getOrder(cust);
// modify order, etc. (an error may occur at any time within this scope)
txScope.VoteCommit();
} // if we voted commit, it will flush/commit otherwise it will rollback