При использовании NHibernate в веб-приложениях я обычно позволяю своему контейнеру IoC позаботиться об открытии и закрытии ISession
на запрос и фиксировать / откатить транзакцию.Природа HTTP позволяет очень легко определить четкую единицу работы в таких приложениях.
Теперь мне было поручено собрать небольшую программу, которая будет регулярно вызываться планировщиком задач,для рассылки новостей.Понятия как информационных бюллетеней, так и подписчиков уже являются четко определенными объектами в нашей модели домена, и отправка информационного бюллетеня всем подписчикам будет включать в себя нечто подобное:
var subscribers = _session
.QueryOver<Subscription>()
.Where(s => !s.HasReceivedNewsletter)
.List();
foreach (var subscriber in subscribers)
{
SendNewsletterTo(subscriber);
subscriber.HasReceivedNewsletter = true;
}
Обратите внимание, как обновляется каждый объект Subscriber
в цикле, запись, что она теперь получила информационный бюллетень.Идея состоит в том, что если программа отправки почты потерпит крах, ее можно будет перезапустить и продолжить отправку информационных бюллетеней с того места, где она остановилась.
Проблема, с которой я сталкиваюсь, заключается в определении и реализации единицы работыобразец здесь.Вероятно, мне потребуется зафиксировать изменения в базе данных к концу каждой итерации цикла.Простое обертывание тела цикла с блоком using (var trans = _session.BeginTransaction())
кажется чрезвычайно дорогим во время выполнения, и я также, похоже, испытываю проблемы с блокировкой между этим долго выполняющимся процессом и другими (веб) приложениями, использующими ту же базу данных.
Прочитав некоторые статьи и документацию по транзакциям NHibernate, я пришел к выводу, что мне может потребоваться отсоединить список подписчиков от сеанса, чтобы избежать проблем с блокировкой, и повторно присоединить каждого к новому сеансу в теле цикла.Однако я не уверен, как это будет работать для повышения производительности.
Итак, эксперты NHibernate, как бы вы спроектировали и внедрили такую долгосрочную работу, как эта?