14

静的なNhibernateISessionFactoryを保持するNHibernateSessionFactoryクラスを作成しました。これは、セッションファクトリが1つしかないことを確認するために使用され、OpenSession()が最初に呼び出されたときに、実際のSessionFactoryを作成します。次に同じものを使用してセッションを開きます。コードは次のようになります。

public class NhibernateSessionFactory : INhibernateSessionFactory
{
    private static ISessionFactory _sessionFactory;

    public ISession OpenSession()
    {
        if (_sessionFactory == null)
        {
            var cfg = Fluently.Configure().
                Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).
                Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());
            _sessionFactory = cfg.BuildSessionFactory();
            BuildSchema(cfg);
        }
        return _sessionFactory.OpenSession();
    }

    private static void BuildSchema(FluentConfiguration configuration)
    {
        var sessionSource = new SessionSource(configuration);
        var session = sessionSource.CreateSession();
        sessionSource.BuildSchema(session);            
    }
}

今、私は問題を抱えています。私のアプリケーションはクライアントとサーバーに分割されています。Nhibernateのものはサーバー側にあります。起動時に、クライアントとサーバーの両方が、NhibernateSessionFactoryを使用するいくつかのサービスを介してデータベースにアクセスしたいと考えています。結果は、要求がクライアントから来る前に_sessionFactoryが作成されるかどうかの競合状態です。そうでない場合は失敗します。

NhibernateSessionFactoryに何らかのキューイングまたは待機メカニズムが必要だと思いますが、どうすればよいかわかりません。誰かが以前に同じ問題を抱えていましたか?最善の解決策は何ですか?

4

2 に答える 2

19

sessionFactoryスレッドセーフなシングルトンである必要があります。

sessionFactoryJavaの一般的なパターンは、静的初期化子でビルドすることです。HibernateUtilを参照してください。C#でも同じことができます。

ロックや同期セクションの使用など、シングルトンを実装する他のパターンがあります。私がそれを正しく理解したならばあなたの問題を解決するはずのわずかな変形がここにあります。

static readonly object factorylock = new object();

public ISession OpenSession()
{
    lock (factorylock)
    {
       if (_sessionFactory == null)
       {
            var cfg = Fluently.Configure().
               Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).
               Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());
            _sessionFactory = cfg.BuildSessionFactory();
            BuildSchema(cfg);
        }
    }
    return _sessionFactory.OpenSession();
}
于 2010-03-02T10:06:46.520 に答える
4

SessionFactory の作成時にMutexを使用してこれを解決しました。これは合理的に見えますか:

public class NhibernateSessionFactory : INhibernateSessionFactory
{
    private static ISessionFactory _sessionFactory;
    private static Mutex _mutex = new Mutex();  // <-- Added

    public ISession OpenSession()
    {
        if (_sessionFactory == null)
        {
            _mutex.WaitOne();              // <-- Added
            if (_sessionFactory == null)   // <-- Added
            {                              // <-- Added
                var cfg = Fluently.Configure().
                    Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).
                    Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());
                _sessionFactory = cfg.BuildSessionFactory();
                BuildSchema(cfg);
            }                              // <-- Added
            _mutex.ReleaseMutex();         // <-- Added

        }
        return _sessionFactory.OpenSession();
    }

    private static void BuildSchema(FluentConfiguration configuration)
    {
        var sessionSource = new SessionSource(configuration);
        var session = sessionSource.CreateSession();
        sessionSource.BuildSchema(session);            
    }
}

魔法のように機能するようです。しかし、代わりにロックを使用する必要がありますか?

于 2010-03-02T10:07:32.617 に答える