更新
我接受了我的回答,因为我相信OnePerRequest模块不应该清除缓存,直到所有其他模块都有机会运行。但是,在我们将其余页面移植到MVC之后,我将重新设计我们的工作单元实现,以更符合Remo的建议。
我刚刚从Ninject 2.0升级到Ninject 2.1,我现在遇到了NHibernate UnitOfWork实现的问题。
我的实施如下。我有一个订阅BeginRequest和EndRequest的HttpModule,并且有以下代码。
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构造函数,再次进入NinjectHttpApplication中的Application_Start方法。
所以它非常令人费解,我发现关闭此功能的方法之一是致电OnePerRequestModule.StopManaging(Kernel);
在Global.asax.cs中的OnApplicationStarted方法中使用两次。有没有人对如何处理这个有任何建议?我假设有一个原因引入了OnePerRequestModule,但是继续我的UnitOfWork实现会很好。
答案 0 :(得分:0)
我认为这不是一个好的实施。您应该在激活操作中调用BeginRequest,在存放库中调用CloseRequest。这样你就没有服务定位器,比如在内核上调用get。
答案 1 :(得分:0)
我已经重写了我的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();
}
}
答案 2 :(得分:-2)
我决定编辑Ninject.Web.Mvc项目来解决这个问题。在NinjectHttpApplication类中。我已将此语句this.onePerRequestModule.Init(this);
从构造函数移动到Init
方法。这可确保onePerRequestModule最后注册其事件处理程序。