开发者

Can an exception during OnRelease cause a component to not be disposed correctly?

开发者 https://www.devze.com 2023-02-14 05:43 出处:网络
I\'ve got the following code wiring a NHibernate ISession in Autofac for a ASP.NET application : builder.RegisterAdapter<ISessionFactory, ISe开发者_如何转开发ssion>(factory => factory.OpenSe

I've got the following code wiring a NHibernate ISession in Autofac for a ASP.NET application :

builder.RegisterAdapter<ISessionFactory, ISe开发者_如何转开发ssion>(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;
                       }
                   }
               });

Will the session be properly disposed even with a thrown exception in the commit? Is this a correct usage of ISession together with autofac?


No- throwing in Dispose() isn't a good idea with Autofac. The correct disposal of other component instances isn't guaranteed.

In general it should be avoided - WCF for example has a well known and long-standing usability problem because connections throw during disposal. The basic antipattern is that Dispose() is often called because an exception is propagating. Throwing a further exception masks the original one

Edit:

As a thought experiment - let's say this was supported using some try/catch magic in Autofac. What happens if OnRelease() throws for two different components? We can't propagate both exceptions. Further - once the exception has bubbled out of Autofac, who can catch it? All of the components servicing the request have now been released.

Hope this helps, Nick.


I don't know about NHibernate ISession in Autofac but if your session class has a Dispose() method then you're not calling it anywhere. You should add a finally block after your catch block and dispose of it there.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号