【问题标题】:Caching Entity Framework DbContexts per request每个请求缓存实体框架 DbContexts
【发布时间】:2011-09-28 16:11:09
【问题描述】:

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

我在 HttpContext.Current.Items 中缓存了它们的副本,因为每个请求都拥有多个副本感觉不对,但我现在发现它不会从 HttpContext 中自动释放请求的结束。在我开始编写代码来处理它之前(在 Application_EndRequest 中),我想我会重新解决这种情况,因为如果我应该在需要它们的地方实例化它们然后在那里处理它们,那么缓存它们真的没有意义。

网上有人问过类似的问题,但我似乎找不到能准确回答我问题的问题。对不起,如果我重复某人的话。

更新

我发现在 this 博客文章中处理上下文可能无关紧要,但我仍然有兴趣了解它们是否首先实例化的成本很高。基本上,我想避免经常在幕后发生很多 EF 魔法吗?

【问题讨论】:

  • 另一个 SO 答案基本上回答了我的问题:here。为了加快创建速度,尽管可以根据this 问题使用缓存的EntityConnection(尽管记住它不是线程安全的很有用)。我还不能回答我自己的问题,所以我会拭目以待,看看是否还有其他候选人。

标签: c# asp.net entity-framework


【解决方案1】:

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

【讨论】:

  • 有什么特别推荐的吗?
  • 如果我必须选择一个没有限制的,我可能会因为熟悉而选择结构图。大多数(如果不是全部)“名称”容器都具有此功能。
【解决方案2】:

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

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

总的来说,实例化 DbContext 并没有那么昂贵,所以不用担心。

此外,您也不必担心如何处理数据上下文。您可能会注意到 ScottGu 在他的示例中没有(他通常将上下文作为控制器上的私有字段)。 This answer 有一些来自 Linq to SQL 团队的关于处理数据上下文的好信息,this 博客文章也扩展了这个主题。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 谢谢。我不明白“您的交易将被提升为分布式”,您能澄清一下吗?您是否需要 处理上下文?更新后的问题中提到的博客文章似乎另有说明,我注意到 Scott Gu 倾向于在他的上下文中使用私有字段,然后不会被处理掉。
    • @Ladislav 的观点与我们特别相关。我们依赖于具有事务范围的多个上下文,这当然会导致事务通过 DTC 进行提升。但是,我们仍然发现实体集的清理效率足够高,不需要强制处理上下文。我知道这不是高效编程或最佳实践,但它确实只是工作。当我们确实强制处理上下文时,还有一个奇怪的副作用,因为应该是同一上下文的独立实例,使用异步,死在我们身上......
    【解决方案4】:

    我们有一个使用与您描述的模式类似的模式的 Web 项目(尽管使用多个独立的 L2S 上下文而不是 EF)。虽然在请求结束时没有dispose context,但我们发现由于HttpContext.Current变成unreferenced,GC适时收集context,导致dispose。我们使用内存分析器确认了这一点。尽管上下文持续的时间比应有的要长一些,但对我们来说是可以接受的。

    自从注意到这种行为后,我们尝试了几种替代方法,包括在 EndRequest 上处理上下文,并在 EndRequest 上强制进行 GC 收集(这不是我的想法,很快就被取消了)。

    我们现在正在研究在请求期间实施包含我们的上下文集合的工作单元模式的可能性。如果您在 google 上搜索,有一些很棒的文章,但对我们来说,可惜的是,实施所需的时间超过了潜在的好处。

    另一方面,我现在正在调查转向组合 SOA/工作单元方法的复杂性,但同样,在没有知识的情况下构建企业规模的应用程序后,这是事后诸葛亮的事情之一。

    我很想听听其他人对该主题的看法。

    【讨论】:

    • 谢谢。我曾认为让 GC '在某个时候'做这件事在重负载下并不好,最好是确定性的,但我会是第一个承认我对那个领域不太了解的人。不过,我不会做 GC.Collect,请参阅this 答案以获得更好的解决方案。我认为您认为缓存上下文是值得的吗?
    • 我认为有一条非常模糊的界限。仅仅由于我们应用程序的结构,除了上下文的单例模式(实现为在 HttpContext 中存储上下文的工厂)之外的任何东西对我们来说都是一个噩梦 - 必须确保实体加载到相关上下文中,确保上下文有使用延迟加载的属性时未处理。我们确实有一个事件,我们在每个请求期间生成的上下文超过了所需的大约 15 个上下文,这可能类似于不缓存上下文。因此,性能受到了严重影响。
    • 这是一个有趣的post,我偶然发现它可能适用于你。我认为这同样适用于 EF 上下文 - 基本上,SQL 连接无论如何都会关闭,所以不要担心处理上下文。
    • 我没有找到那个帖子,所以谢谢你的链接。还有一点需要注意的是,当我在 due course 中提到 GC 处理我们的上下文时,分析器显示它们在请求完成后几乎立即被丢弃 - 在上下文中返回大型结果集时尤其明显。我找不到为什么存在这种行为 - 我的第一个想法是请求完成时会自动发生 gen1 集合,但这并没有真正加起来。这绝对是您需要运行一些性能监控以查看最适合您的事情之一。祝你好运!
    猜你喜欢
    • 1970-01-01
    • 2012-12-13
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-10-29
    • 2013-04-05
    • 2020-06-10
    • 1970-01-01
    相关资源
    最近更新 更多