繁体   English   中英

使用AutoFac在ASP.net MVC筛选器中的NHibernate工作单元

[英]NHibernate unit of work in ASP.net MVC filter using AutoFac

我正在尝试使用NHibernate和Transactions创建每个请求的工作单元。 我在MVC中有一个全局应用的过滤器。 看起来如下。

public class TransactionAttribute : ActionFilterAttribute
{
    private ISession _session;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //Constructor does NOT get run per request. 
        _session = DependencyResolver.Current.GetService<ISession>();
        _session.FlushMode = FlushMode.Commit;
        _session.BeginTransaction();

        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Exception == null)
        {
            _session.Transaction.Commit();
        }
        else
        {
            _session.Transaction.Rollback();
        }

        _session.Dispose();

        base.OnActionExecuted(filterContext);
    }
}

请注意,我正在使用依赖关系解析程序来获取服务,这意味着它被称为每个请求,而不是被缓存的构造函数,否则我就被认为是。

现在,我的Autofac模块如下所示:

public class AutoFacModule
{
    public static IContainer Build()
    {
        return Build(new ContainerBuilder());
    }

    public static IContainer Build(ContainerBuilder builder)
    {

        // You can register controllers all at once using assembly scanning...
        builder.RegisterControllers(typeof(MvcApplication).Assembly);
        builder.RegisterModule<AutofacWebTypesModule>();

        builder.Register(x => NHibernateSetup.CreateSessionFactory()).SingleInstance();
        builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerHttpRequest();

        //Build Registry. 
        var returnContainer = builder.Build();

        DependencyResolver.SetResolver(new AutofacDependencyResolver(returnContainer));

        return returnContainer;
    }
}

因此,据此,我认为每个HTTP请求都会获得一个新的_session。 但这似乎并非如此。 如果我在MVC动作中插入断点并加载页面,等待它到达断点,然后启动一个新选项卡并加载同一页面,等待它到达断点,然后继续进行下去。 我收到一个错误:

Transaction not successfully started

当我尝试提交时。 我相信这是因为第一个请求已经提交了事务。 这似乎是因为两个请求都共享一个ISession,而不是每个请求都唯一。

发布到StackOverflow的行为突然使一切都变得有意义。

因此,由于某种原因,它与全局注册过滤器有关。 因为我有点懒,所以我做了以下工作

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new TransactionAttribute());
}

因此,基本上将每个请求包装在事务中。 在使用DependencyResolver时,这似乎不起作用。 如果我删除了它,然后将属性直接添加到方法上,则一切开始起作用。

作为一个站点说明,我还发现了一种不使用Autofac而无需使用构造函数来注入属性的方法: http ://alexmg.com/filterattribute-property-injection-in-autofac-mvc-3-integration/,这似乎是默认设置autofac下处理过滤器时的方法。

关于这种方法的一些事情让我有些不高兴,因为拥有这样的属性公共似乎有点奇怪(因为除了在构造函数中,任何人都不应设置它)。 但是,它确实使事物能够进行单元测试(尽管我假设依赖关系解析器方式也具有可以进行单元测试的方式)。

因此,现在,我将属性直接放在动作上。 但这可能需要加以考虑,因为诸如日志记录/错误处理之类的可能肯定需要注入的东西会出现在globalfilters集合中?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM