NHibernate Session ObjectDisposedException

3

有没有办法验证NHibernate是否已经释放了Session?

我有一个Session的包装类,它有自己的Finalizer和IDispoable实现,但是如果Session在我处理它之前被释放,我会收到ObjectDisposedException。

我真的不想用以下方式包装我的清理代码:

try {
...
}
catch (ObjectDisposedException) { }

但是我不确定是否有其他方法。 Session.IsOpen和Session.IsActive属性似乎没有提供任何可靠的信息,我可以确认会话是否已被处理。

您可以在Assembla上查看完整源代码

3个回答

1

好的,我刚刚看了一下你的代码。 我不确定这是否是问题所在,但你正在从对话dispose方法中调用End(), 这将尝试重新连接并处理会话,如果在此之前已经显式调用了End(),则会出现问题,请避免该调用。 我认为在会话dispose之前回滚事务是不必要的,因为这是隐含完成的。 我只是快速浏览了一下,但我真的很喜欢你的实现。


您说得对,因为在我的单元测试结束时,当我尝试重新连接时,会出现已处理异常,此时会话始终处于 isopen = true,isconnected = false 的状态。我只是不明白为什么在基础连接已释放的情况下,isopen 属性仍然为 true。 - Chris Marisic
也许你是对的,我也不应该在意,因为似乎总是被处理掉了。你看过我关于整个业务交易模式的博客了吗?http://dotnetchris.wordpress.com/2009/01/27/conversation-per-business-transaction-using-postsharp-and-ioc/ - Chris Marisic

0
"

那是我见过的最荒谬的事情之一,即使在处理后仍保持其Open属性。

为什么一个已经处理的对象会包含可靠的状态信息呢?您不应尝试使用已处理的会话,我不知道nhibernate正在哪里处理您的会话,您确定没有自己处理它吗?

"

我的目标是自己处理它,但在我的单元测试期间,它似乎总是在我的对象之前被处理掉了。如果它没有被处理掉,我想回滚它的事务(如果有的话),否则显式调用关闭然后处理。但问题是该对象没有提供任何方法来告诉它是否已经被处理掉了。 - Chris Marisic

0

我一直认为NHibernate的最佳实践是“每个请求一个会话”,这意味着它应该只存在于“using”范围内。

using(Session session = new Session())
{
}

我建议尝试防止两个人处置会话/对话。如果您控制会话的创建,可以将其包装在您自己的ISession实现中,该实现执行自己的IsAlreadyDisposed()检查以防止异常。不过,考虑到这样做带来的努力与“预期异常”相比,原始代码看起来并不那么糟糕。

我还建议注意您的终结器实现。 “Session.Is().InTransaction()”转到Session->Transaction,而会话可能在终结器完成之前为空。在终结器时间导航托管关系不能保证能够工作。


我使用NH的SessionFactory创建会话,但我不确定如何使用自定义会话类,除非下载源代码并进行修改。然而,如果我只想这样做,我会在调用会话的Dispose()方法时将IsOpen返回false。 - Chris Marisic
"Session has been disposed of by NHibernate already"?这是在什么情况下发生的?我已经很久没用NHibernate了,但我不记得它会自己释放会话。 - Quibblesome
你的会话策略是什么?你是在整个应用程序中使用一个会话还是每个请求使用一个会话? - Quibblesome
每个 HttpSession 一次会话,我使用面向方面的编程来允许我将多个操作分组到单个事务中。这通常意味着每个请求一个事务,比每个请求创建一个新会话更有效率,它是会话每个请求的继承者。 - Chris Marisic
我在这个主题上有一篇博客文章:http://dotnetchris.wordpress.com/2009/01/27/conversation-per-business-transaction-using-postsharp-and-ioc/ 当我在单元测试结束时进行应用程序拆除时遇到了这个异常,目前正在尝试解决这个问题。 - Chris Marisic
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接