使用NInject在一个衍生的线程中定义NHibernate ISession

时间:2010-07-12 19:58:34

标签: asp.net nhibernate backgroundworker repository-pattern ninject

好的,这是场景。我有一个ASP.NET站点,定期生成一个后台线程来做一些工作。线程的执行包含一个JobRunner,它遍历IJobs列表并在每个IJobs上调用Execute()。 JobRunner和每个IJob都是由NInject创建的。一些IJobs依赖于IRepository< ModelType>。我正在使用的IRepository的实现是针对NHibernate的,所以它有一个ISession的构造函数参数。到目前为止,我已经让NInject从ISessionFactory返回一个ISession,作用于每个Request(InRequestScope)。

问题在于:当各种IJobs进行处理(涉及保存到IRepository)时,数据永远不会被持久化,因为ISession.Flush()永远不会被调用。每个IJob都不知道它正在使用的IRepository的实现。同样,JobRunner对它正在运行的IJobs的实现一无所知。对于Web应用程序的其余部分,它工作正常,因为在Application_EndRequest中调用了ISession.Flush()。

我尝试将ISession作为构造函数参数添加到JobRunner中,以便在所有IJobs完成处理时可以调用Flush(),但它似乎获得了与IJobs不同的ISession(调用session.GetHashCode()为JobRunner返回不同的值,但对于所有IJobs,它都是相同的)。我根据HttpContext将NInject配置为范围ISession(如果有),否则使用CurrentThread。我认为,由于JobRunner是在一个单独的线程上,它将获得一个限制为CurrentThread的ISession,并且因为所有IJobs都在与JobRunner相同的线程上运行,所以它们都应该获得相同的ISession,但它们不是。

所以我的问题是,有没有更好的方法去做我想做的事情?任何人都知道为什么我会在同一个线程上为不同的请求获取不同的ISession实例?

现在我有一个解决方法 - 我将session.Flush()作为我的NHibernateRepository.Save()方法的最后一行,但我对此并不满意。

1 个答案:

答案 0 :(得分:1)

我找到了解决方案。我的JobRunner对象是在Global.asax的Application_Start方法中实例化的,因此持有该线程ID而不是后台线程ID。

我创建了一个包装类,它接受一个类型并使用NInject创建一个实例,每次后台线程开始处理时,它都使用包装类来获取JobRunner的实例。在正确的线程上创建它,这允许我获得与我的IRepository相同的ISession,所以我可以在所有IJobs完成后调用session.Flush()。

也许有一个更优雅的解决方案,但在此之前,这很有效。