【问题标题】:EF5 (entity framework) memory leak and doesn't release after disposeEF5(实体框架)内存泄漏并且在处置后不释放
【发布时间】:2014-03-14 17:19:16
【问题描述】:

所以我使用 web api 来公开数据服务。最初,我将 dbcontext 创建为静态内存,每次在 IISExpress 下打开项目时,内存都会膨胀到超过 100MB。我知道由于此处已解决的答案,不建议使用静态:

Entity framework context as static

所以我继续将我的应用程序转换为使用常规的非静态 dbcontext 并在我的 api 中包含一个 dispose 方法:

     protected override void Dispose(Boolean disposing)
    {
        if (provider.Context != null)
        {
            provider.Context.Dispose();
            provider = null;
        }
        base.Dispose(disposing);
    }

现在每次我打电话时,它都会通过这个方法并进行处理。现在,我打开应用程序,仍然气球到100k,每次打电话时,我都会查看我的iisexpress进程的内存,它一直在上升,并且在dispose后不再下降,它一直在增加到几乎200MB+。

不管是不是静态的,只要我使用它,内存就会爆炸。

最初我认为是我的 web api 导致了它,直到我删除了所有服务并在我的 api 中创建了 EF 对象(我使用的是breathjs,所以这段代码很简单,实际的实现在下面,但对内存消耗没有影响):

private DistributorLocationEntities context = new DistributorLocationEntities();

然后 bam,立即 110MB。

在我使用它时如何释放内存有什么有用的提示和调整吗?我应该在我的 dispose() 中添加垃圾收集吗?像这样快速分配和释放内存有什么陷阱吗?例如,我每次敲击键以完成“自动完成”功能时都会调用该服务。

我也不确定如果我把它投入生产会发生什么,我们有几十个用户访问数据库;我不希望用户将内存增加到 1 或 2GB 并且它不会被释放。

旁注:我现在所有的数据服务都是搜索,所以没有保存更改或更新,尽管以后可能会有。此外,我不会将任何 linq 查询作为数组或可枚举返回,它们在整个服务调用过程中仍然是可查询的。

还有一件事,我确实使用了微风,所以我将我的上下文总结如下:

readonly EFContextProvider<DistributorLocationEntities> provider = new EFContextProvider<DistributorLocationEntities>();

以及随之而来的花絮:

Doc for Breeze's EFContextProvider proxycreationenabled = 假
ladyloadingenabled = 假
不包括 idispose

但无论如何我仍然处理上下文,这没有区别。

【问题讨论】:

    标签: asp.net-web-api entity-framework-5 breeze


    【解决方案1】:

    我不知道你在做什么。我知道您的 Web API 控制器中不应该有任何类型的静态资源(无论是否微风)。

    我强烈怀疑你违反了这条规则。

    添加Dispose 方法没有区别,如果对象从未被释放...如果它保存在静态变量中,则不会。

    我认为 Breeze 在您的问题中没有任何作用。你已经证明它没有。

    我建议您从头开始,暂时忘记 Breeze,获取一个简单的 Web API 控制器,为每个请求创建一个 DbContext。当你弄清楚这一点后,继续添加一些 Breeze。

    【讨论】:

    • 嗨,沃德,我知道为什么 EF 会爆炸,感谢您的回复。我很好地阅读了这篇文章:msdn.microsoft.com/en-us/data/hh949853.aspx,我关闭了某些上下文的自动缓存,并发现“包含”会降低 EF 性能(但在 EF6 中已修复)。性能影响不是来自 web api 或微风控制器。一如既往地感谢您的输入:)
    【解决方案2】:

    正如 Ward 的评论中提到的,静态是一个很大的禁忌,所以我花时间将我的 EF 对象移出静态。 Dispose 方法也没有真正的帮助。

    我很好地阅读了这篇文章:

    http://msdn.microsoft.com/en-us/data/hh949853.aspx

    EF 提供了很多性能选项(不是开箱即用的)。所以这里有一些我做过的事情:

    • 为 EF 添加了预生成的视图:T4 templates for generating views for EF4/EF5。这样做的好处是它从数据库中抽象出来并预先生成视图以减少模型加载时间
    • 接下来,我阅读了这篇关于包含在 EF 中的帖子:Why does the Contains() operator degrade Entity Framework's performance so dramatically?。显然,我看到了一个将 IEnumerable.Contains 转换为 HashSet.Contains 的有吸引力的答案。这大大提高了我的表现。
    • 最后,阅读微软的文章,我意识到有一个“AsNoTracking()”可以连接到 DBContext,这会在 linq 中自动缓存特定的上下文。所以你可以做这样的事情

      var query = (from t in db.Context.Table1.AsNoTracking() select new { ... }

    我不必担心在 EF5 中编译查询,因为它会自动为您完成,因此您不必添加 CompileQuery.Compile()。此外,如果您使用的是 EF 6 alpha 2,则无需担心包含或预生成视图,因为该版本已修复此问题。

    所以当我启动我的 EF 时,这是一个“冷”查询执行,我的内存变高了,但是在回收 IIS 之后,内存被减半并使用“热”查询执行。这解释了很多!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-26
      • 1970-01-01
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      • 2011-01-27
      相关资源
      最近更新 更多