2015-04-05 60 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集合中?