Удостоверьтесь, что NHibernate SessionFactory только создается однажды

Я записал класс NHibernateSessionFactory, который содержит статический Nhibernate ISessionFactory. Это используется, чтобы удостовериться, что у нас только есть одна фабрика сессии, и в первый раз, когда OpenSession () называют, я создаю actuall 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, но я не уверен в том, что сделать. У кого-либо была та же проблема прежде? Каково лучшее решение?

14
задан stiank81 2 March 2010 в 09:51
поделиться

2 ответа

sessionFactory должен быть потокобезопасным синглтоном.

Общим шаблоном в Java является создание sessionFactory в статическом инициализаторе. See HibernateUtil. То же самое можно сделать и в C#.

Существуют и другие паттерны для реализации singleton, включая использование блокировки или синхронизированных секций. Вот небольшой вариант, который должен решить вашу проблему, если я правильно понял.

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();
}
19
ответ дан 1 December 2019 в 12:26
поделиться

Я решил это с использованием Mutex при создании SessionFactory. Выглядит ли это разумно:

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);            
    }
}

Кажется, работает чудо. Но следует ли мне использовать вместо этого блокировку?

4
ответ дан 1 December 2019 в 12:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: