2

Хорошо, вот сценарий. У меня есть сайт ASP.NET, который периодически создает фоновый поток для выполнения некоторых заданий. выполнение потока состоит из JobRunner, который выполняет итерацию через список IJob и вызывает Execute() для каждого из них. JobRunner и каждый IJob создается NInject. Пара IJobs имеет зависимость от IRepository <ModelType>. Реализация IRepository, которую я использую, для NHibernate, поэтому у нее есть аргумент конструктора для ISession. До сих пор у меня было NInject, возвращающее ISession из ISessionFactory, охваченного каждым запросом (InRequestScope).scobe NHibernate ISession в порожденной теме с NInject

Вот проблема: когда различные IJobs выполняют свою обработку (что связано с сохранением в IRepository), данные никогда не сохраняются, потому что ISession.Flush() никогда не вызывается. Каждый IJob ничего не знает о реализации используемого IRepository. Аналогично, JobRunner ничего не знает о реализации запущенных IJob. Для остальных веб-приложений он работает нормально, потому что ISession.Flush() вызывается в Application_EndRequest.

Я попытался поставить ISession в качестве аргумента конструктора в JobRunner, чтобы я мог вызвать Flush() на нем, когда все IJobs обработаны, но похоже, что он получает другое ISession, чем IJobs (вызов session.GetHashCode () возвращает разные значения для JobRunner, но для всех IJobs это одно и то же). Я настроил NInject на область ISession на основе HttpContext, если она есть, в противном случае используйте CurrentThread. Я понял, что, поскольку JobRunner находится в отдельном потоке, он получит ISession, привязанный к CurrentThread, и поскольку все IJob запускаются в том же потоке, что и JobRunner, все они должны получить одинаковое ISession, но это не так.

Итак, мой вопрос: есть ли лучший способ сделать то, что я пытаюсь сделать? Кто-нибудь знает, почему я получаю другой экземпляр ISession для разных запросов в одном потоке?

На данный момент у меня есть обходное решение - я поставил session.Flush() как последнюю строку моего метода NHibernateRepository.Save(), но я не доволен этим.

ответ

1

Я нашел решение. мой объект JobRunner создавался в методе Application_Start для Global.asax и, таким образом, содержал этот идентификатор потока вместо идентификатора потока фона.

Я создал класс-оболочку, который принимает тип и использует NInject для создания экземпляра, и каждый раз, когда поток фона приходит, чтобы начать обработку, он использует класс-оболочку, чтобы получить экземпляр JobRunner. который создает его на правильном потоке, который позволяет мне получить тот же ISession, что и мой IRepository, поэтому я могу вызвать session.Flush() после завершения всех IJob.

Возможно, есть более элегантное решение, но до тех пор это хорошо работает.

Смежные вопросы