OnePerRequestModule в Ninject, вызывающий открытие нового сеанса NHibernate в EndRequest - PullRequest
0 голосов
/ 17 декабря 2010

UPDATE

Я принял свой ответ, так как считаю, что модуль OnePerRequest не должен очищать кеш, пока все другие модули не смогут запустить. Однако после того, как мы перенесем остальные наши страницы в MVC, я переделываю нашу реализацию Unit of Work, чтобы она больше соответствовала предложению Remo.

Я только что обновил Ninject 2.0 до Ninject 2.1, и теперь у меня возникают проблемы с моей реализацией NHibernate UnitOfWork.

Моя реализация заключается в следующем. У меня есть HttpModule, который подписывается на BeginRequest и EndRequest и имеет следующий код.

public void BeginRequest(object sender, EventArgs e)
{
 var app = (WebApplication)sender;
 var repository = app.Kernel.Get<IRepository>();

 repository.BeginRequest();
}

public void EndRequest(object sender, EventArgs e)
{
 var app = (WebApplication)sender;
 var repository = app.Kernel.Get<IRepository>();

 repository.EndRequest();
}

Реализация IRepository принимает NHibernate ISession в качестве зависимости. Вот две привязки.

Bind<ISession>().ToMethod(context => NHibernateSessionFactory.Instance.OpenSession()).InRequestScope();
Bind<IRepository>().To<NHibernateRepository>().InTransientScope();

Репозиторий NHibernate открывает транзакцию в BeginRequest и фиксирует ее в EndRequest. С обновлением до Ninject 2.1. OnePerRequestModule теперь мешает этому коду. Поскольку он сначала присоединяется к событию EndRequest, он запускается раньше, чем мой DataModule, и очищает ISession из кэша ядра. Это означает, что IRepository получает новую ISession и, следовательно, не может совершить транзакцию. Сложным является тот факт, что OnePerRequestModule регистрируется в Ядре не один, а два раза. Один раз в конструкторе KernelBase и еще раз в методе Application_Start в приложении NinjectHttpApplication.

Так что это довольно запутанно, и я нашел один из способов отключить эту функцию - позвонить OnePerRequestModule.StopManaging(Kernel); дважды в методе OnApplicationStarted в моем Global.asax.cs. У кого-нибудь есть какие-либо предложения относительно того, как справиться с этим? Я предполагаю, что есть причина, по которой был представлен OnePerRequestModule, но было бы неплохо придерживаться моей реализации UnitOfWork.

Ответы [ 3 ]

0 голосов
/ 18 декабря 2010

Я думаю, что это не очень хорошая реализация. Вы должны скорее вызвать BeginRequest в действии активации и CloseRequest в распоряжении хранилища. Таким образом у вас не будет слишком локатора службы, как, например, вызовы get в ядре.

0 голосов
/ 25 февраля 2011

Я переписал свою реализацию UnitOfWork, поскольку мы переписали наше приложение WebForms в MVC.Теперь у меня есть FilterAttribute, который применяется к каждому инкапсулированному действию данных, которое выглядит следующим образом:

public class UnitOfWorkAttribute : FilterAttribute, IActionFilter
{
    [Inject]
    public IUnitOfWork UnitOfWork { get; set; }

    public UnitOfWorkAttribute()
    {
        Order = 0;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        UnitOfWork.Begin();
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        UnitOfWork.End();
    }
}
0 голосов
/ 17 декабря 2010

Я решил отредактировать проект Ninject.Web.Mvc, чтобы исправить это. В классе NinjectHttpApplication. Я переместил это утверждение this.onePerRequestModule.Init(this); из конструктора в метод Init. Это гарантирует, что onePerRequestModule зарегистрирует свой обработчик событий последним.

...