Can an exception during OnRelease cause a component to not be disposed correctly?
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.
精彩评论