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

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?

没有正确的解决方案

其他提示

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top