NHibernate 幫助類(單例實際運用)

  在NHibernate中,ISessionFactory是線程安全的,對應一個數據庫。它是生成ISession的工廠。而ISession是線程不安全的。javascript

  建立一個ISessionFactory須要消耗比較多的資源。所以,咱們只在程序初始化的時候建立一次,之後就一直使用這個ISessionFactory。html

  而ISession的建立只消耗不多的資源。所以咱們能夠隨意建立。java

1、原始單例模式封裝的ISessionFactory

  所以,對於ISessionFactory,咱們使用餓漢單例模式實現它。git

  原始餓漢單例模式封裝ISessionFactory實例:數據庫

複製代碼
      //密封類
        public sealed class NSession
        {
            //私有、靜態、只讀
            private static readonly ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();

            //私有構造函數,防止new
            private NSession()
            {

            }

            public static ISessionFactory GetSessionFactory()
            {
                return sessionFactory;
            }
        }
複製代碼

  OK,對於ISessionFactory,以上代碼就可以保證,整個程序只有一個SessionFactory的實例了。設計模式

  雖然,上面的代碼已經使用單例模式實現了SessionFactory只能保證只有一個實例。可是,實際上咱們可以進一步封裝,實現管理到ISession。由於在咱們的程序當中,咱們實際上使用的是ISession。而咱們要獲得ISession對象,每次都要在代碼裏調用安全

  ISession iSession = NSession.GetSessionFactory().OpenSession();

  這樣的代碼來得到ISession對象。咱們何不乾脆封裝到ISession呢?session

2、利用HttpContext綁定ISession

  上面說到,咱們實際上要用到的是ISession對象而不是ISessionFactory對象。因此,咱們乾脆封裝到ISession,實現更簡單的調用。框架

  咱們,先來看看如下代碼的問題:數據庫設計

複製代碼
    //密封類
    public sealed class NSession
    {
        //私有、靜態、只讀
        private static readonly ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();

        //私有構造函數,防止new
        private NSession()
        {

        }

        //返回ISession
        public static ISession GetSession()
        {
            return sessionFactory.OpenSession();
        }
    }
複製代碼

  測試代碼:

複製代碼
        public PersonModel GetPerson(int Id)
        {
            ISession iSession1 = NSession.GetSession();
            ISession iSession2 = NSession.GetSession();
            HttpContext.Current.Response.Write(object.ReferenceEquals(iSession1, iSession2));   //輸出 False,這是兩個ISession對象
            return iSession1.Get<PersonModel>(Id);
        }
複製代碼

  咱們看到,倘若咱們想上面那種封裝方法,只要調用了一次GetSession()方法,就會生成一個新的ISession對象,雖然這樣ISession佔用的資源很少,但總感受有多少浪費,咱們何不將ISession綁定到HttpContext中,實現對於一次Http請求,只建立一個ISession呢?

複製代碼
    //密封類
    public sealed class NSession
    {
        //私有、靜態、只讀
        private static readonly ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();

        //私有構造函數,防止new
        private NSession()
        {

        }

        //獲取ISession
        public static ISession GetSession()
        {
            HttpContext context = HttpContext.Current;
            ISession currentSession = context.Items["ISession"] as ISession;
            //若是對於本次請求的HttpContext裏尚未ISession對象,才OpenSession(),同時存入HttpContext中,用於下次判斷和Close()
            if (currentSession == null)
            {
                currentSession = sessionFactory.OpenSession();
                context.Items["ISession"] = currentSession;
            }

            return currentSession;
        }

        //關閉ISession
        public static void CloseSession()
        {
            HttpContext context = HttpContext.Current;
            ISession currentSession = context.Items["ISession"] as ISession;
            //若是對於本次請求尚未建立ISession對象,那就用不着關閉了
            if (currentSession != null)
            {
                currentSession.Close();
                context.Items.Remove("ISession");
            }
        }

        //關閉SessionFactory
        public static void CloseSessionFactory()
        {
            if (sessionFactory != null)
            {
                sessionFactory.Close();
            }
        }
    }
複製代碼

  咱們再來測試下:

複製代碼
        public PersonModel GetPerson(int Id)
        {
            ISession iSession1 = NSession.GetSession();
            ISession iSession2 = NSession.GetSession();
            HttpContext.Current.Response.Write(object.ReferenceEquals(iSession1, iSession2));   //輸出 True,這是兩個ISession對象
            return iSession1.Get<PersonModel>(Id);
        }
複製代碼

  此次是輸出True了。說明,這兩個是同一個對象。

  以上代碼就實現了HttpContext與ISession對象掛鉤,對於一次HttpContext只建立一個ISession。當請求響應完畢,HttpContext裏面的ISession就自動釋放掉了。對於在請求響應未完畢以前,該ISession都一直處於打開狀態(例如渲染視圖時),不影響操做。

  以上代碼依賴於HttpContext,所以只適合於Web程序。

3、非Web程序中封裝ISession

  而對於在WinForm或控制檯項目中,因爲程序是跑在客戶端上,一個客戶端電腦,哪怕你Open好幾百個ISession都沒什麼問題,只是要管理好ISessionFactory,由於ISessionFactory仍是比較佔用資源的。

  對於非Web程序中的NHibernate幫助類實現以下:

複製代碼
    public sealed class NSession
    {
     private static readonly ISessionFactory sessionFactory; static NSession() { sessionFactory = new Configuration().Configure().BuildSessionFactory(); } public static ISession GetSession() { return sessionFactory.OpenSession(); } public static void CloseSession(ISession currentSession) { if (currentSession != null) { currentSession.Close(); } } public static void CloseSessionFactory() { if (sessionFactory != null) { sessionFactory.Close(); } } }
複製代碼

 

 
 
 
0
0
 
(請您對文章作出評價)
 
« 上一篇: HttpContext請求上下文對象
» 下一篇: 物理數據庫設計 - 限定列的有效值
相關文章
相關標籤/搜索