在OnRelease期间发生异常会导致组件无法正确释放吗?

3
我可以为ASP.NET应用程序在Autofac中连接NHibernate ISession的代码如下:

我有以下代码来在Autofac中连接NHibernate ISession:

builder.RegisterAdapter<ISessionFactory, ISession>(factory => factory.OpenSession())
    .InstancePerHttpRequest()
    .OnActivated(activatedArgs =>
                 {
                     var session = activatedArgs.Instance;
                     session.BeginTransaction();
                 })
    .OnRelease(session =>
               {
                   if (session.Transaction != null && session.Transaction.IsActive)
                   {
                       try
                       {
                           session.Transaction.Commit();
                       }
                       catch(Exception e)
                       {
                           session.Transaction.Rollback();
                           throw;
                       }
                   }
               });

即使在提交时发生异常,会话是否会被正确处理?这是否是ISession与autofac的正确使用方式?

2个回答

2
不要在Autofac中使用 Dispose(),这样会导致其他组件实例的正确释放无法得到保证。通常应该避免这种情况。例如,WCF由于连接在释放期间抛出异常而存在已知和长期存在的易用性问题。基本反模式是通常调用Dispose()是因为异常正在传播。抛出更多异常会掩盖原始异常。
编辑:假设使用一些try/catch魔法在Autofac中支持此功能。如果 OnRelease() 为两个不同的组件抛出异常怎么办?我们无法同时传播两个异常。此外,一旦异常从Autofac冒泡出来,谁能捕获它?所有服务请求的组件现在都已被释放。希望这可以帮助你,Nick。

OnRelease()方法在组件被Dispose()时调用,所以这样做不是一个好主意?我的想法是在每次使用会话时将会话使用情况包装在事务中。我能否请您提供该行为的另一种实现方式? - Bruno Lopes
嗨,布鲁诺 - 如果您正在使用MVC,则在自定义操作调用程序中调用Commit()是我所知道的最佳选项。 - Nicholas Blumhardt
我正在使用WebForms,所以也许我会在HttpModule上完成这个。我认为这只是引发了一个问题,即如果没有完成任何工作,则不创建/提交事务。 - Bruno Lopes

0
我不了解Autofac中的NHibernate ISession,但如果您的会话类有Dispose()方法,则您没有在任何地方调用它。您应该在catch块之后添加finally块,并在那里处理它。

Autofac 的一部分工作是在组件被释放时进行处理。我的问题与使用 OnRelease 有关,如果在此处抛出异常,Autofac 是否仍然在将异常传递给调用链之前/之后进行处理。如果是这样的话,在此处调用 Dispose 将是不正确的,因为它也会在调用链上进一步调用。 - Bruno Lopes
@Bruno,如果他们的实现正确,在这里处理它应该不会有任何问题。您可以尝试一下,看看是否会出现ObjectDisposed异常:)很抱歉我对Autofac等不是很了解,所以无法提供更多帮助。 - Shiv Kumar

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