【翻译】提示18——如何决定ObjectContext的生命周期
作者:Alex D James
我们经常碰到一个问题是ObjectContext应对存活多久。经常被引用的选项包括:
- 函数(Function)
- 窗体(Form)
- 线程(Thread)
- 应用程序(Application)
很多人都在问这类型的问题,典型的例子是在Stackflow上的问题。我相信有更多的类似问题被埋没在我们的论坛上。
这是一个经典的取决于类型的问题。
做出决定有许多权衡因素,主要包括:
- 处置(Disposal):
干净处置ObjectContext和它的资源是很重要的。如果为每一个函数创建一个新的ObjectContext,这会容易很多,因为可以简单的使用using块来确保适当的释放资源。
using (MyContext ctx = new MyContext()) { … }
- 构建的花费(Cost Of Construction):
许多人比较关注重一次又一次的重新创建ObjectContext的花费,这完全可以理解。现实情况是这种成本其实很低,因为大部分时候,它只涉及到通过引用将元数据从全局缓存中复制到新的ObjectContext。基本上,我不认为这种成本是值得担心的,但一如既往,这规则存在例外情况。
- 内存使用(Memory Usage):
越多的使用一个ObjectContext,基本上它就会越占内存。这是因为,基本上无论是查询、添加或附加,它都要保存对所有实体的引用。因此,必须考虑无限期地共享相同的ObjectContext所存在的问题。尽管对于这种情况有一些例外和解决办法,但大部分时候,不建议这样做。
○ 如果ObjectContext只是执行NoTracking查询,那么它不会变大,因为它会立即忘记这些实体。
○可以实现一些非常明确的善后逻辑,即实现某种形式的循环接口,遍历ObjectStateManager中分离的实体和AcceptingChanges(..) 来放弃删除对象。注意:我不建议这样,我只是说,它应用有可能,因为我不知道相对于重新创建,它是否会导致保存。这也许是未来博客文章的一个好题材。
- 线程安全(Thread Safety):
如果尝试去重用一个ObjectContext,你应该知道,它不是线程安全的,这类似于标准的.NET集合类。如果你从许多线程(如web请求)中访问它,你就要确保手动进行同步访问。
- 无状态(Stateless):
如果你的服务被设计为无状态的,其实大多数Web服务应该是这样,在请求之间重用ObjectContext可能不是最好的,因为最后一次通话的ObjectContext的残余(leftovers)可能会产生微秒的影响,而这并不是应用程序所预期的。
- 自然有限的生命周期(Natural finite lifetimes):
如果你使用一个自然有限的生命周期的方式来管理ObjectContext,如一个短周期的窗体,一个UnitOfWork,或一个存储库,那么有作用范围的ObjectContext可能是最好的实现。
正如你所看到的,有许多因素在起作用。
他们中的大多数倾向于短生命周期的上下文,而不是共享的。
因此,这就是我推荐的法则。
然后,只有了解了这背后的“推理法则”,才有助于在适当的时候采用适合自己的方式。