6

我有一个 Windows 服务,其中包含一个文件观察程序,当文件到达时会引发事件。当一个事件被引发时,我将使用 Ninject 创建业务层对象,这些对象在它们内部具有对实体框架上下文的引用,该上下文也通过 Ninject 注入。在我的 Web 应用程序中,我总是使用 InRequestScope 作为上下文,这样在一个请求中,所有业务层对象都使用相同的实体框架上下文。在我当前的 Windows 服务场景中,将实体框架上下文绑定切换到 InThreadScope 绑定就足够了吗?

理论上,当服务中的事件处理程序触发它在某个线程下执行时,如果另一个文件同时到达,它将在另一个线程下执行。因此,这两个事件都不会共享实体框架上下文,本质上就像网络上的两个不同的 http 请求一样。

困扰我的一件事是这些线程范围对象的破坏,当您查看 Ninject wiki 时:

.InThreadScope()- 每个线程将创建一个该类型的实例。
.InRequestScope()- 每个网络请求都会创建一个该类型的实例,并在请求结束时销毁。

基于此,我了解 InRequestScope 对象将在请求结束时(或之后的某个时间点)被销毁(垃圾收集?)。然而,这并没有说明 InThreadScope 对象是如何被销毁的。回到我的示例,当文件观察程序事件处理程序方法完成时,线程消失(回到线程池?)注入的 InThreadScope-d 对象会发生什么?

编辑: 现在有一点很清楚,当使用 InThreadScope() 时,当文件观察程序的处理程序退出时,它不会破坏您的对象。我能够通过在文件夹中删除许多文件来重现这一点,最终我得到了相同的线程 id,这导致了与以前完全相同的实体框架上下文,所以这对于我的应用程序来说绝对是不够的。在这种情况下,5 分钟后进入的文件可能正在使用之前分配给同一线程的陈旧上下文。

4

1 回答 1

4

Objects that are thread-static could possibly live for a very long time, which means that at some time that ObjectContext will get stale and work with old (cached) values, which will result in hard-to-find bugs.

I normally create an ObjectContext with the same scope as I create a database transaction (I often even wrap a ObjectContext in a database transaction and dispose them right after each other). One (web) request could possibly have multiple database transactions, but will usually have one 'business transaction', which executes the business logic. Other transactions could be started for things as logging (before, after, and sometimes during the business transaction). When you reuse the ObjectContext for the complete request you could end up with a mess, because when a business transaction fails, the ObjectContext could be in an invalid state, which might have effect on operations (such as logging) that reuse that same ObjectContext.

With your Windows Service, I think every event raised by the file watcher possibly triggers a new business transaction. In that case I would create a new ObjectContext per event.

Long story short, I would not inject an ObjectContext that has a lifetime that is managed by your IoC framework. I would inject a factory that allows your code to create a new ObjectContext and dispose it. I just answered another question about this a few ours back. Look at the solution I propose in that answer.

Good luck.

于 2010-12-23T13:49:21.823 回答