2011-09-09 85 views
4

所以問題在這裏。我有一個通用的類庫,它包含所有的存儲庫,域和映射文件,以便該庫可以在其他Web應用程序中重用。現在在這個類庫中有一段代碼,它允許自己創建一個會話工廠以用於其存儲庫。代碼看起來像這樣。NHibernate SessionFactory線程安全問題

 private static ISessionFactory sessionFactory; 
     private static Configuration configuration; 

     public static Configuration Configuration() 
     { 
      if (configuration == null) 
      { 
       configuration = new Configuration().Configure(); 
      } 
      return configuration; 
     } 

     private static ISessionFactory SessionFactory 
     { 
      get 
      { 
       if (sessionFactory == null) 
       { 
        sessionFactory = Configuration().BuildSessionFactory(); 
       } 
       return sessionFactory; 
      } 
     } 

     public static ISession GetCurrentSession() 
     { 
      if (!CurrentSessionContext.HasBind(SessionFactory)) 
      { 
       CurrentSessionContext.Bind(SessionFactory.OpenSession()); 
      } 
      return SessionFactory.GetCurrentSession(); 
     } 

因此,存儲庫調用GetCurrentSession()方法來獲得一個ISession。現在這工作正常,但我擔心它可能不是線程安全的。任何人都可以幫助我採取一種方法來幫助我使線程安全。

幾點需要注意:

我曾想過配置並在啓動事件的Web應用程序,但這樣做的問題是,有問題的共同類庫使用的Global.asax建設的SessionFactory在20個不同的應用程序中,所以這將意味着去所有的應用程序和更新global.asax文件之前,我這樣做我想提出的問題,看看是否有任何其他方式,我可以去做這件事。以便公共類庫可以配置其SessionFactory本身,但是線程安全。

感謝您閱讀這個巨大的問題。將幫助任何幫助。

回答

6

會話工廠是線程安全的,會話不是。建立會話工廠需要保護:

private static object lockObject = new object(); 

    private static ISessionFactory SessionFactory 
    { 
     get 
     { 
      lock (lockObject) 
      { 
       if (sessionFactory == null) 
       { 
        sessionFactory = Configuration().BuildSessionFactory(); 
       } 
       return sessionFactory; 
      } 
     } 
    } 

的會話工廠第一次創建一個線程請求會話。這需要是線程安全的,以避免多次創建會話工廠。

會話工廠創建會話是線程安全的,因此您不必擔心這一點。

+0

謝謝你的Stefan。關於鎖定上述代碼的快速問題。鎖確保每個線程都有自己的SessionFactory,並且兩個或多個Session工廠不是在同一個線程上創建的? – Bobby

+0

不,該鎖讓第一個線程進入並創建靜態會話工廠。第二個線程需要等到第一個線程離開鎖定範圍。當第二個進來時,會話工廠已經創建並且只需要它。如果沒有鎖定,會話工廠將並行創建多次。 –

+0

這很合理:o) – Bobby

0

我建議使用一個會話每個請求是這樣的:

public ISession GetCurrentSession() 
{ 
     HttpContext context = HttpContext.Current; 

     var currentSession = context.Items["session"] as ISession; 

     if(currentSession is null) 
     { 
      currentSession = SessionFactory.GetCurrentSession() 
      context.Items["session"] = currentSession; 
     } 

     return currentSession; 
} 
+0

注意:除了上述內容,我建議使用NHibernate上下文會話的正確配置(http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-current-session),應該沒有需要在HttpContext.Current中另外添加會話(再次,順便說一句,因爲這是NH在內部IIRC中所做的)。只要你需要它就問SessionFactory.GetCurrentSession()。 –