補充的原因:針對 session 的管理有點頭疼!
《NHibernate 設定檔的處理和使用多資料庫的多層架構思路》(一)中底層的思路只適合單線程的情況!比如這類簡單的 MIS 系統:一個或是多個用戶端安裝在各自的機器上串連同一個或是多個資料庫。因為針對一個資料庫僅緩衝了一個 session 對象。多線程很顯然就不適用了!比如針對ASP.NET, .Net Remoting,上面的結構就不適用了!就算是簡單的 Mis 系統,也盡量將 session 用完就關掉(Disconnect()),需要的時候重新開啟(Reconnect()),由session的屬性IsConnected 來判斷。我在(一)中的底層的EntityControl類與session相關的各個方法中沒有這樣做。但是這個補充部分完成了的!
另外,有時可能會遇見這個異常:a different object with the same identifier value was already associated with the session: 2, of class: ..... .這是因為 session 是個全域的一直儲存著,如果先用 AddEntity(obj) , 它裡面就含了一個對象 obj,後來又使用了 UpdateEntity(obj1, obj1.Id); 而obj1.Id和 obj.Id一樣且obj和obj1不是指向同一個對象。解決方案是:要麼保證obj1和obj指向同一個對象(就是先從session取出 obj,然後給它的屬性賦值),要麼在兩步操作的中間使用session.Clear()。
如果要解決多線程問題怎麼辦?主要問題在於管理 session 對象上!
雖然可以針對(一)中 EntityControl 類中在每個方法中都聲明 session 的局部變數,然後由 SessionFactory 類提供建立新的 session 對象,這種解決方案可以構成通殺,單線程,多線程都適用,但是效率低下,不適合我們的需求。如果我們解決了session 對象的管理,只需要在前面的思路中對 SessionFactory 類重寫 public ISession OpenSession(); 方法即可。其他的變化均 session 對象的管理相關。也就是說,只有底層中只有一兩個類有變化,其他層不發生任何變化,不影響多層架構思路.
具體情況具體對待了!(其實我都不想寫下去了,因為有很多不錯的文章,比如《NHibernate的Session管理》已經把我馬上要列舉的兩類情況都包含進去了!只是由於以前寫(一)、(二)、(三)這三部分,我還是有責任把沒有說清楚的地方解釋清楚,更重要的是給自己做個筆記以便自己查閱,有錯誤的地方也可以晾出來讓大家給指出來。另外我和他們一小點不同的地方是我針對於多個資料庫操作的。)
處理兩種具體情況:
第一種情況:ASP.NET。
它的特點是為每個使用者提供一個 session 是最好的。顯然又不可能為每個使用者一直儲存獨立 的 session。那麼為請求服務的每個活動線程提供一個 session,這樣也不夠好,因為每個請求可以涉及到多個線程,大家用的都是同一個 session,何必為涉及到的多個線程提供單獨的 session 呢?現在情況就明朗,為每個請求提供一個 session, 請求結束時 session 釋放。
網上已經有很多文章解決這個問題了。我只簡單提一下:在每次 request 請求模式,在第一次使用時建立一個 session(不是在context.。BeginRequest 時就建立session),request 請求模式結束時(context.EndRequest)釋放session 。
(1) 配置 web.config
<httpModules>
<add name="NHibernateModule" type="NHibernate.Helper.Module, NHibernate.Helper" />
</httpModules>
(2)建立請求模式結束需要使用的類。
//-----------------------------------------------------------------------------------------
//參考地址:http://blogs.intesoft.net/simon/articles/16.aspx
//-----------------------------------------------------------------------------------------
using System;
using System.Web;
namespace NHibernate.Helper
{
public sealed class Module : IHttpModule
{
public void Init(HttpApplication context)
{
context.EndRequest += new EventHandler(EndRequest);
}
public void Dispose() { }
public void EndRequest(Object sender, EventArgs e)
{
SessionFactory.CloseSession();
}
}
}
(3)建立包含所有操作的類。省略了一些代碼。這個東西很久以前就有了,所以我都不好意思寫太多。
//-----------------------------------------------------------------------------------------
//參考地址:http://blogs.intesoft.net/simon/articles/16.aspx
//-----------------------------------------------------------------------------------------
using System;
using System.Web;
using System.Configuration;
using NHibernate;
using NHibernate.Cfg;
namespace NHibernate.Helper
{
public sealed class SessionFactory
{
private static readonly Configuration configuration = new Configuration();
private static readonly ISession session = sessionFactory.OpenSession();
private static readonly ISessionFactory sessionFactory = configuration.Configure( HttpContext.Current.Request.MapPath(ConfigurationSettings.AppSettings["nhibernate.config"]) ).BuildSessionFactory();
[CLSCompliant(false)]
public static ISession Session
{
get
{
ISession session;
if (HttpContext.Current == null)
{
session =SessionFactory.session;
}
else
{
if (HttpContext.Current.Items.Contains(sessionKey))
{
session = (ISession)HttpContext.Current.Items[sessionKey];
}
else
{
session = SessionFactory.sessionFactory.OpenSession();
HttpContext.Current.Items[sessionKey] = session;
}
}
return session;
}
}
[CLSCompliant(false)]
public static void CloseSession()
{
if (HttpContext.Current == null)
{
SessionFactory.session.Close();
}
else
{
if (HttpContext.Current.Items.Contains(sessionKey))
{
ISession session = (ISession)HttpContext.Current.Items[sessionKey];
session.Close();
HttpContext.Current.Items.Remove(sessionKey);
}
}
}
}
其它四部分地址:
NHibernate 設定檔的處理和使用多資料庫的多層架構思路(第一部分)
http://blog.csdn.net/scucj/archive/2007/05/16/1610858.aspx
NHibernate 設定檔的處理和使用多資料庫的多層架構思路(第二部分)
http://blog.csdn.net/scucj/archive/2007/05/16/1610860.aspx
NHibernate 設定檔的處理和使用多資料庫的多層架構思路(第三部分)
http://blog.csdn.net/scucj/archive/2007/05/16/1610861.aspx
NHibernate 設定檔的處理和使用多資料庫的多層架構思路(補充部分二)
http://blog.csdn.net/scucj/archive/2007/05/16/1612323.aspx
參考資料:
(1) NHibernate的Session管理
http://blog.csdn.net/thebesghost/archive/2006/08/23/1107151.aspx
(2)多線程下WinForm開發應該注意哪些問題?
http://www.cnblogs.com/Cajon/archive/2007/03/21/Multi_Thread_Win_Form.html
(3)NHibernate.Helper Project:
http://blogs.intesoft.net/simon/articles/16.aspx