Autofac, NHibernate ISession and MVC transaction-per-request. What does properly working with a Session and Transaction look like?

StackOverflow https://stackoverflow.com/questions/22134951

Question

I'm using AutoFac to implement a Transaction-per-Request pattern in MVC. I have the following:

public static void RegisterDaoFactory()
{
    var containerBuilder = new ContainerBuilder();

    containerBuilder.RegisterControllers(Assembly.GetAssembly(typeof(Streamus)));
    containerBuilder.Register(x => NHibernateSessionManager.Instance.SessionFactory).SingleInstance();
    containerBuilder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerHttpRequest();
    containerBuilder.Register(x => LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType)).As<ILog>().InstancePerHttpRequest();

    IContainer container = containerBuilder.Build();
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

public abstract class StreamusController : Controller
{
    protected readonly ILog Logger;
    protected new readonly ISession Session;
    private ITransaction Transaction;

    protected StreamusController(ILog logger, ISession session)
    {
        if (logger == null) throw new ArgumentNullException("logger");
        if (session == null) throw new ArgumentNullException("session");

        Logger = logger;
        Session = session;
    }

    protected override void OnActionExecuting(ActionExecutingContext actionContext)
    {
        base.OnActionExecuting(actionContext);

        Transaction = Session.BeginTransaction();
    }

    protected override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);

        try
        {
            if (Transaction.IsActive)
            {
                if (actionExecutedContext.Exception != null)
                    Transaction.Rollback();
                else
                    Transaction.Commit();
            }
        }
        finally
        {
            Transaction.Dispose();
        }
    }

    protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new JsonNetResult
        {
            Data = data,
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            JsonRequestBehavior = behavior
        };
    }

}

Autofac opens and closes the ISession for me like a champ. I'm pretty sure I need to handle disposing of the transaction myself.

Am I missing anything?

No correct solution

OTHER TIPS

I would call BeginTransaction() directly in the controller actions, where and when you need it. You usually want the transaction to have the shorter lifespan possible. Also, this way you have the choice not to open a transaction in the cases you don't need it, like a redirection.

Also, don't forget to use

using(var transaction = Session.BeginTransaction())
{
    // Database code here
}
so your transaction is always disposed, exception or not.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top