Управление сессиями NHibernate в приложениях службы Windows - PullRequest
11 голосов
/ 05 октября 2008

Я разрабатываю и приложение, которое работает как служба Windows. Существуют и другие компоненты, которые включают несколько служб WCF, клиентский графический интерфейс и т. Д., Но это - служба Windows, которая обращается к базе данных.

Итак, приложение - это долго работающий сервер, и я хотел бы улучшить его производительность и масштабируемость, я стремился улучшить доступ к данным среди прочего. Я написал в другой ветке о кэшировании второго уровня.

Этот пост посвящен управлению сессиями для долго работающего потока, который обращается к базе данных. Должен ли я использовать поток-статический контекст? Если да, то есть ли пример того, как это будет реализовано?

Кажется, что каждый в сети, кто использует NHibernate, сильно сосредоточен на архитектурах стиля веб-приложений. Похоже, что существует нехватка документации / обсуждения для не-веб-приложений.

В данный момент моя длинная ветка делает это:

  1. Вызов 3 или 4 метода DAO
  2. Проверка состояния возвращенных отсоединенных объектов.
  3. Обновите состояние, если необходимо.
  4. Вызовите несколько методов DAO, чтобы сохранить обновленные экземпляры. (передайте идентификатор объекта и самого экземпляра - DAO снова получит объект из БД и установит обновленные значения и session.SaveOrUpdate () перед принятием транзакции.
  5. Сон 'n' секунд
  6. Повторите все заново!

Итак, следующая общая схема, которую мы используем для каждого из методов DAO:

  • Открыть сессию с помощью sessionFactory.OpenSession ()
  • Начать транзакцию
  • ДБ работает. получить / обновить и т. д.
  • Совершить транс
  • (откат в случае исключений)
  • Наконец, всегда удаляйте транзакцию и сессию. Close ()

Это происходит для каждого вызова метода класса DAO. Я подозреваю, что это своего рода анти-паттерн, как мы это делаем.

Однако я нигде не могу найти достаточно указаний относительно того, как мы могли бы его улучшить.

Обратите внимание, что пока этот поток работает в фоновом режиме и выполняет свои функции, поступают запросы от клиентов WCF, каждый из которых может сам выполнять 2-3 вызова DAO, иногда запрашивая / обновляя одни и те же объекты в течение длительного времени нить имеет дело с

Будем весьма благодарны за любые идеи / предложения / указатели по улучшению нашего дизайна. Если мы сможем провести хорошую дискуссию, мы сможем сделать это вики-сообществом, и, возможно, ссылку здесь с http://nhibernate.info

Кришна

Ответы [ 5 ]

7 голосов
/ 05 октября 2008

Похоже, что не хватает документации / обсуждения для не-веб-приложений.

Это тоже мой опыт. Однако модель, которой вы придерживаетесь, кажется мне правильной. Вы всегда должны открывать сеанс, фиксировать изменения, а затем снова закрывать его.

1 голос
/ 03 марта 2011

Этот вопрос уже немного устарел, но другим методом будет использование контекстных сессий, а не создание новой сессии в каждой DAO.

В нашем случае мы думаем создать сеанс один раз для потока (для нашей многопоточной службы win32) и сделать его доступным для DAO, используя либо свойство, которое возвращает SessionFactory.GetCurrentSession () (используя ThreadContext текущий поставщик сеанса, так что это сеанс на поток) или через DI (внедрение зависимостей - еще раз с использованием ThreadContext.)

Подробнее о GetCurrentSession и Contextual Sessions здесь .

0 голосов
/ 04 мая 2011

Недавно мы начали использовать контейнер IoC для управления жизненным циклом сеанса в качестве замены для контекстных сеансов, упомянутых выше. (Подробнее здесь ).

0 голосов
/ 12 марта 2010

Вы также можете очистить сеанс, не закрывая его, и он достигает того же самого. Я делаю.

0 голосов
/ 27 ноября 2008

Я согласен, примеров для приложений с состоянием не так много. Я думаю сделать следующее:

Как и у вас, у меня есть служба Windows, на которой размещен ряд служб WCF. Таким образом, сервисы WCF являются точками входа. В конечном итоге все мои WCF-сервисы наследуются от AbstractService, который обрабатывает много журналов и основных вставок / обновлений БД.

В одном из лучших постов NHibernate, которые я видел, HttpModule делает следующее: см http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx

private void BeginTransaction(object sender, EventArgs e) {
    NHibernateSessionManager.Instance.BeginTransaction();
}
private void CommitAndCloseSession(object sender, EventArgs e) {
    try {
        NHibernateSessionManager.Instance.CommitTransaction();
    }
    finally {
        NHibernateSessionManager.Instance.CloseSession();
    }
}

Так что, возможно, мне следует сделать нечто подобное в AbstractService. Таким образом, в результате я получу сеанс для каждого вызова службы. Если вы изучите ссылку на статью о лучших практиках NHib выше, то увидите, что NHibernateSessionManager должен иметь дело со всем остальным, пока я открываю и закрываю сеанс (конструктор и деструктор AbstractService).

Просто мысль. Но у меня возникают ошибки, потому что мой сеанс, кажется, слишком долго зависает, и я получаю печально известную ошибку - NHibernate.AssertionFailure: нулевой идентификатор в записи (не очищайте сеанс после возникновения исключения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...