2015-04-05 63 views
0

我试图使用NHibernate和事务每个请求创建一个工作单元。我在MVC中有一个全局应用的过滤器。它看起来像下面。使用AutoFac的ASP.net MVC过滤器的NHibernate单元使用AutoFac

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 Action中插入一个断点,然后加载一个页面,等待它到达断点,然后启动一个新标签并加载相同的页面,等待它到达断点,然后让这两个断点继续。我得到一个错误:

Transaction not successfully started 

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

回答

0

发布到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下处理滤镜时的默认方式。

有关这种方法的一些事情让我感到有点不高兴,因为拥有这样的属性似乎有点奇怪(因为它实际上不应该由ANYON设置,除非在构造函数中)。但是,它确实使得单元测试成为可能(虽然我认为依赖解析器的方式也可以单元测试)。

所以现在,我会将属性直接放在动作上。但是可能需要将它看作是可能需要注入的日志记录/错误处理等东西才在globalfilters集合中?