2

好的,這是場景。我有一個ASP.NET網站,定期產生後臺線程做一些工作。線程的執行由一個JobRunner組成,該JobRunner迭代IJob列表並在每個列表上調用Execute()。 JobRunner和每個IJob都由NInject創建。一些IJob對IRepository <ModelType>有依賴性。我使用的IRepository的實現是用於NHibernate,所以它有一個ISession的構造函數參數。到目前爲止,我已經讓NInject從一個ISessionFactory返回一個ISession,作用於每個Request(InRequestScope)。確定NHibernate ISession在一個產生的線程與NInject

下面是問題:當各種IJob執行它們的處理(涉及到保存到IRepository)時,數據永遠不會被保存,因爲ISession.Flush()永遠不會被調用。每個IJob都不知道它使用的IRepository的實現。同樣,JobRunner不知道它正在運行的IJobs的實現。對於Web應用程序的其餘部分,它工作正常,因爲ISession.Flush()在Application_EndRequest中被調用。

我嘗試把ISession作爲構造函數參數給JobRunner,這樣我可以在所有IJob完成處理時調用Flush(),但它似乎獲得與IJobs不同的ISession(調用session.GetHashCode( )爲JobRunner返回不同的值,但是對於所有的IJobs都是一樣的)。我將NInject配置爲基於HttpContext的範圍ISession(如果有),否則使用CurrentThread。我認爲,由於JobRunner在一個單獨的線程上,它將得到一個ISession範圍爲CurrentThread,並且由於所有IJob都與JobRunner在同一個線程上運行,它們應該都獲得相同的ISession,但它們不是。

所以我的問題是,有沒有更好的方法來做我想做的事情?任何人都知道爲什麼我會爲同一線程上的不同請求獲取不同的ISession實例?

現在我有一個解決方法 - 我把session.Flush()作爲我的NHibernateRepository.Save()方法的最後一行,但我對此並不滿意。

回答

1

那麼我找到了解決方案。我的JobRunner對象在Global.asax的Application_Start方法中被實例化,並且因此保持該線程ID而不是後臺線程ID。

我創建了一個包裝類,它接受一個類型並使用NInject創建一個實例,每次後臺線程開始處理時,它都會使用包裝類來獲取JobRunner的一個實例。它在適當的線程上創建它,它允許我獲得與IRepository相同的ISession,所以我可以在所有IJobs完成後調用session.Flush()。

也許有一個更優雅的解決方案,但在此之前,這工作得很好。