2011-09-09 6 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(); 
     } 

ので、リポジトリはISessionを取得するGetCurrentSession()メソッドを呼び出します。これでうまくいきますが、スレッドセーフではないかもしれないと心配しています。私はそれをスレッドセーフにするのに役立つ方法で誰かを助けることができますか?注意する

いくつかのこと:

私は開始イベントでの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

ステファンに感謝します。上記のコードでロックに関する簡単な質問。ロックは、各スレッドが独自のSessionFactoryを持ち、2つ以上のSessionファクトリが同じスレッド上に作成されないことを保証しますか? – Bobby

+0

いいえ、ロックにより、最初のスレッドが入ってきて静的セッションファクトリが作成されます。 2番目のスレッドは、最初のスレッドがロックスコープを離れるまで待機する必要があります。後者が来ると、セッションファクトリが作成され、それだけが必要になります。ロックがなければ、セッションファクトリは複数回並列に作成されます。 –

+0

それは完璧です:o) – Bobby

0

セッションは、設計によってNHibernateでスレッドセーフではありません。したがって、1つのスレッドによって使用されているセッションがである限り、問題ありません。 あなたは下のリンクを見てい限り、あなたはより多くの情報のために、各スレッド

用に別のNHibernateのセッションを持っているように、複数のスレッドのための1のNHibernateのSessionFactoryを持つことができます:私は1つを使用することをお勧め

https://forum.hibernate.org/viewtopic.php?p=2373236&sid=db537baa5a57e3968abdda5cceec2a24

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()に問い合わせてください。 –

関連する問題