EF5(实体框架)内存泄漏并且在处理后不释放

时间:2014-03-14 17:19:16

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

所以我使用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进程的记忆,并且它继续上升并且在处理后它没有回落,它一直在增加到几乎200MB +。

无论是否静态,只要我使用它,内存就会爆炸。

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

private DistributorLocationEntities context = new DistributorLocationEntities();

和bam,立即110MB。

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

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

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

还有一件事,我确实使用了breezejs,所以我就这样结束了我的上下文:

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

以及随之而来的花絮:

Doc for Breeze's EFContextProvider proxycreationenabled = false
ladyloadingenabled = false
idispose不包括在内

但是我仍然会处理上下文,这没什么区别。

2 个答案:

答案 0 :(得分:2)

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

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

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

我不相信Breeze在你的问题中有任何作用。你已经表明它没有。

我建议你从一个干净的平板开始,暂时忘记Breeze,得到一个简单的Web API控制器,每个请求创建一个DbContext。当你想出来之后,继续添加一些微风。

答案 1 :(得分:2)

正如沃德的评论中提到的,静力学是一个很大的禁忌,所以我花时间将我的EF对象移出静态。处理方法也没有任何帮助。

我给这篇文章写了很好的读物:

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的有吸引力的答案。这大大提升了我的表现。
  • 最后,阅读微软的文章,我意识到有一个&#34; AsNoTracking()&#34;您可以连接到DBContext,这将转换为linq中特定上下文的自动缓存。所以你可以做这样的事情

    var query =(来自db.Context.Table1.AsNoTracking()中的t选择新的{...}

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

因此,当我启动我的EF时,这是一个很冷的&#34;查询执行,我的记忆力很高,但在回收IIS之后,内存被减少一半并使用&#34; warm&#34;查询执行。所以这解释了很多!