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

发布于 2024-10-08 09:41:57 字数 1488 浏览 2 评论 0原文

更新

我已经接受了我的答案,因为我相信 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();
}

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 实现。

UPDATE

I've accepted my answer since I believe that the OnePerRequest module shouldn't clear out the cache until all other modules have had a chance to run. However, after we port the rest of our pages to MVC I will be reworking our Unit of Work implementation to be more in line with Remo's suggestion.

I just upgraded from Ninject 2.0 to Ninject 2.1 and I'm now having issues with my NHibernate UnitOfWork implementation.

My implementation is as follows. I have an HttpModule that subscribes to BeginRequest and EndRequest and has the following code.

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();
}

The IRepository implementation takes an NHibernate ISession as a dependency. Here are the two bindings.

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

NHibernate repository opens up a transaction in BeginRequest and commits it in EndRequest. With the upgrade to Ninject 2.1. The OnePerRequestModule is now interfering with this code. Since it is attached to the EndRequest event first it fires before my DataModule and clears the ISession from the Kernel cache. This means that the IRepository gets a brand new ISession and thus can't commit the transaction. Complicating matters is the fact that OnePerRequestModule registers with the Kernel not once, but twice. Once in the KernelBase constructor and once again in the Application_Start method in the NinjectHttpApplication.

So it's pretty convoluted and one of the ways I've found to turn this functionality off is to call OnePerRequestModule.StopManaging(Kernel);
twice in the OnApplicationStarted method in my Global.asax.cs. Does anyone have any suggestions in regards to how to handle this? I'm assuming there's a reason OnePerRequestModule was introduced, but it would be nice to keep with my UnitOfWork implementation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

2024-10-15 09:41:57

我认为这不是一个好的实施。您应该在激活操作中调用 BeginRequest,并在存储库的处置中调用 CloseRequest。这样你就不需要像内核上的 get 调用那样的服务定位器。

I think that's not a good implementation. You should rather call BeginRequest in a activation action and CloseRequest in the dispose of the repository. That way you do not have thes too service locator like get calls on the kernel.

妖妓 2024-10-15 09:41:57

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

I've rewritten my UnitOfWork implementation as we have rewritten our WebForms app to MVC. I now have a FilterAttribute that is applied to every data encapsulated action that looks like this:

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();
    }
}
梦毁影碎の 2024-10-15 09:41:57

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

I've decided to edit the Ninject.Web.Mvc project to fix this. In the NinjectHttpApplication class. I've moved this statement this.onePerRequestModule.Init(this); from the constructor to the Init method. This ensures that the onePerRequestModule registers its event handler last.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文