2008-10-05 96 views
11

我正在開發和作爲Windows服務運行的應用程序。還有其他的組件,其中包括幾個WCF服務,一個客戶端GUI等 - 但它是訪問數據庫的Windows服務。Windows服務應用程序中的NHibernate會話管理

因此,該應用程序是一個長期運行的服務器,我想提高其性能和可伸縮性,我期待着改善數據訪問等。我發佈了另一個關於二級緩存的主題。

這篇文章是關於訪問數據庫的長時間運行的線程的會話管理。 我應該使用線程靜態上下文嗎? 如果是這樣,是否有任何如何實施的例子。每個使用NHibernate的網絡用戶似乎都非常關注Web應用程序樣式體系結構。非網頁應用程序設計似乎缺乏文檔/討論。

此刻,我的長期運行的線程做這樣的:

  1. 呼叫3種或4 DAO方法
  2. 驗證分離對象的狀態恢復。
  3. 如果需要更新狀態。
  4. 調用幾個DAO方法來保存更新的實例。 (傳入對象的id和實例本身--DAO將再次從DB檢索對象,並在提交事務之前設置更新值和session.SaveOrUpdate()。
  5. 睡眠時間爲'n'秒
  6. 重複一遍

因此,以下是我們使用的每一個DAO方法的通用模式:

    使用sessionFactory.OpenSession
  • 打開的會話()
  • 開始交易
  • 做db工作。檢索/更新等
  • 提交反式
  • (回滾在例外的情況下)
  • 最後總是處置交易和session.Close()

出現這種情況方法調用一個DAO類。 我懷疑這是某種反模式,我們正在這樣做。

但是,我無法找到足夠的方向,以至於我們無法改進它。

請注意,雖然此線程在後臺運行,但在執行其任務時,有來自WCF客戶端的請求,每個客戶端都可以自行進行2-3個DAO調用 - 有時查詢/更新相同的對象正在運行的線程處理。

任何想法/建議/指針,以改善我們的設計將不勝感激。 如果我們能得到一些很好的討論繼續下去,我們能做出這樣一個社區維基,並possbily從http://nhibernate.info

這裏鏈接到克里希納

回答

7

似乎是一個偉大的缺乏對非文檔/討論web應用程序設計。

這也是我的經驗。但是,您所遵循的模型對我來說似乎是正確的。您應該始終打開一個會話,提交更改,然後再關閉它。

+1

+1。我幾次看到這個一般性建議:SessionFactory是昂貴的。只創建一次。會議很便宜。 – snicker 2010-03-11 21:59:09

0

我同意,有狀態應用程序的例子並不多。 我正在考慮做以下事情:

像你一樣,我有一個Windows服務託管一些WCF服務。所以WCF服務是入門點。 最終,我所有的WCF服務都從AbstractService繼承 - 它處理大量的日誌記錄和基本的DB插入/更新。

在我見過的最好的NHibernate的職位之一,一個HTTP模塊執行以下操作: 看到http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx

private void BeginTransaction(object sender, EventArgs e) { 
    NHibernateSessionManager.Instance.BeginTransaction(); 
} 
private void CommitAndCloseSession(object sender, EventArgs e) { 
    try { 
     NHibernateSessionManager.Instance.CommitTransaction(); 
    } 
    finally { 
     NHibernateSessionManager.Instance.CloseSession(); 
    } 
} 

所以也許我應該做AbstractService類似的東西。如此有效,我將最終得到每個服務調用的會話。如果您查看上面的NHib最佳實踐文章鏈接,只要打開和關閉會話(AbstractService構造函數和析構函數),就會看到NHibernateSessionManager應該處理所有其他事情。

只是一個想法。但是我遇到了錯誤,因爲我的會話似乎掛了很長時間,而且我得到了臭名昭着的錯誤 - NHibernate.AssertionFailure:入口中的空id(發生異常後不刷新會話)。

0

您也可以在不實際關閉的情況下刷新會話並達到同樣的效果。我做。

1

這個問題現在有點老了,但另一種技術是使用上下文會話,而不是在每個DAO中創建新會話。在我們的例子中,我們正在考慮爲每個線程創建會話(對於我們的多線程win32服務),並且使用返回SessionFactory.GetCurrentSession()的屬性將其提供給DAO(使用ThreadContext當前會話提供程序,因此它是每個線程的會話)或通過DI(依賴注入 - 再次使用ThreadContext。)

More info on GetCurrentSession and Contextual Sessions here

0

我們最近開始使用IoC容器來管理會話生命週期,作爲上述上下文會話的替代。 (更多細節here)。