Ninject中的OnePerRequestModule导致在EndRequest时打开新的NHibernate会话

Ninject中的OnePerRequestModule导致在EndRequest时打开新的NHibernate会话,nhibernate,asp.net-mvc-2,ninject,Nhibernate,Asp.net Mvc 2,Ninject,更新 我接受了我的答案,因为我认为OnePerRequest模块在所有其他模块都有机会运行之前不应该清除缓存。然而,在我们将剩下的页面移植到MVC之后,我将重新设计我们的工作单元实现,以便更符合Remo的建议 我刚从Ninject 2.0升级到Ninject 2.1,现在我的NHibernate UnitOfWork实现出现了问题 我的实现如下。我有一个HttpModule,它订阅BeginRequest和EndRequest,并具有以下代码 public void BeginRequest(o

更新

我接受了我的答案,因为我认为OnePerRequest模块在所有其他模块都有机会运行之前不应该清除缓存。然而,在我们将剩下的页面移植到MVC之后,我将重新设计我们的工作单元实现,以便更符合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();
}
public void BeginRequest(对象发送方,事件参数e)
{
var-app=(WebApplication)发送方;
var repository=app.Kernel.Get();
repository.BeginRequest();
}
public void EndRequest(对象发送方,事件参数e)
{
var-app=(WebApplication)发送方;
var repository=app.Kernel.Get();
EndRequest();
}
IRepository实现将NHibernate会话作为依赖项。下面是两个绑定

Bind<ISession>().ToMethod(context => NHibernateSessionFactory.Instance.OpenSession()).InRequestScope();
Bind<IRepository>().To<NHibernateRepository>().InTransientScope();
Bind().ToMethod(context=>NHibernateSessionFactory.Instance.OpenSession()).InRequestScope();
绑定().To().InTransientScope();
NHibernate存储库在BeginRequest中打开一个事务,并在EndRequest中提交它。升级到Ninject 2.1之后。OnePerRequestModule现在正在干扰此代码。因为它首先附加到EndRequest事件,所以它在my DataModule之前触发,并从内核缓存中清除ISession。这意味着IRepository获得了一个全新的ISession,因此无法提交事务。更复杂的是,OnePerRequestModule向内核注册不是一次,而是两次。一次在KernelBase构造函数中,一次在NinjectHttpApplication的应用程序启动方法中

所以它非常复杂,我发现关闭此功能的方法之一是调用
OnePerRequestModule.stopmanagement(内核)

在my Global.asax.cs中的OnApplicationStarted方法中执行两次。有人对如何处理这个问题有什么建议吗?我假设引入OnePerRequestModule是有原因的,但最好保留我的UnitOfWork实现。

我决定编辑Ninject.Web.Mvc项目来解决这个问题。在NinjectHttpApplication类中。我已经移动了这个语句
this.onePerRequestModule.Init(this)
从构造函数到
Init
方法。这确保onePerRequestModule最后注册其事件处理程序。

我认为这不是一个好的实现。您应该在激活操作中调用BeginRequest,在处置存储库中调用CloseRequest。这样你就不会有太多的服务定位器,比如内核上的get调用。

我已经重写了我的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();
    }
}

那么,您会在每个请求中使用一个IRepository吗?我在考虑如何提高我的UoW。这可能是一个很好的方法。我还不能完全做到这一点,因为我正在将一个WebForms项目转换为MVC,但一旦转换完成,我肯定要看它。这取决于应用程序。通常,我会使用多个存储库(遵循DDD规则的不同存储库,例如ICCustomerRepository、IOrderRepository或IRepository)。我不会做的是你现在正在做的事情。事务的打开和关闭应由容器决定。这样,您就不必关心请求使用了哪些存储库。容器将知道这一点并打开和关闭事务。从技术上讲,存储库并没有什么不同,因为它们获得相同的会话。我可以很容易地获得会话并打开和关闭事务,这实际上就是这里正在发生的事情。