关于c#:每个请求缓存实体框架DbContexts

Caching Entity Framework DbContexts per request

我有几个基于System.Entity.Data.DbContext的类。它们在Web应用程序的不同端被多次使用一个请求——实例化它们是否昂贵?

我在httpcontext.current.items中缓存了它们的副本,因为我觉得每个请求都有好几个副本是不对的,但现在我发现在请求结束时,它不会自动从httpcontext中释放。在我开始编写代码来处理它之前(在应用程序的endrequest中),我认为我应该重新处理这种情况,因为如果我只是在需要的地方实例化它们,然后在那里处理它们,就没有必要缓存它们。

类似的问题在互联网上被问过,但我似乎找不到一个准确回答我的问题。对不起,如果我在重复别人的话。

更新

我发现在这个博客文章中处理上下文可能并不重要,但我仍然感兴趣的是,首先要知道它们是否昂贵。基本上,是否有很多英孚魔术在幕后进行,我想避免做太频繁?


最好的办法是在这里使用IOC容器来管理生命周期——它们非常非常擅长这一点,这是一个非常常见的场景。具有使动态调用变得容易的额外优势——这意味着样式表的请求不会创建DB上下文,因为它是在beginRequest()中硬编码的。


为了完整起见,我自己回答问题。

此答案提供了有关此问题的更多信息。

总之,实例化dbContext没有那么贵,所以不用担心。

此外,您也不必担心处理数据上下文。您可能会注意到Scottgu的示例中没有(他通常将上下文作为控制器上的私有字段)。这个答案包含了Linq-to-SQL团队关于处理数据上下文的一些很好的信息,并且这个博客文章也扩展了这个主题。


使用HttpContext.Items并在EndRequest中手动处理上下文—您甚至可以为此创建自定义HTTP模块。这是正确的处理方法。上下文处理还将释放对所有被跟踪实体的引用,并允许GC收集它们。

如果您确实需要每个请求,可以使用多个上下文,但在大多数情况下,一个上下文就足够了。如果您的服务器处理是一个逻辑操作,那么您应该为整个工作单元使用一个上下文。如果在事务中进行更多的更改,这一点尤其重要,因为在多个上下文中,您的事务将升级为分布式事务,并且会对性能产生负面影响。


我们有一个使用类似于您描述的模式的Web项目(尽管使用多个独立的L2S上下文而不是EF)。尽管在请求结束时上下文未被释放,但我们发现,由于httpcontext.current未被引用,gc会及时收集上下文,导致在场景下进行释放。我们用记忆分析仪证实了这一点。虽然上下文的持续时间比它应该的要长一些,但我们可以接受。

由于注意到了这种行为,我们尝试了两种选择,包括在endrequest上处理上下文,并在endrequest上强制GC收集(这一个不是我的主意,很快就消失了)。

我们现在正在研究实现一个工作单元模式的可能性,这个工作单元模式包含我们在请求期间收集的上下文。如果你用谷歌搜索的话,有一些很棒的文章,但是对我们来说,遗憾的是,实施所需的时间超过了潜在的好处。

另一方面,我现在正在研究迁移到一个结合的SOA/工作单元方法的复杂性,但同样,在构建了一个企业级的应用程序之后,如果没有知识的话,这也是事后诸葛亮的事情之一。

我很想听听别人对这个问题的看法。