【发布时间】:2013-03-18 00:30:28
【问题描述】:
全部,
是否可以从会话对象(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() 和处置。但是,如果会话发生错误,我将无法刷新会话!
一种解决方法是不提供原始休眠会话,而是提供一个带有执行会话操作的方法的包装器对象,这样我就可以在 try/catch 中包装任何操作并知道错误发生的时间。如果你问我,那是愚蠢的解决方法。
另一个选项是所有 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
【问题讨论】:
标签: .net winforms nhibernate