首页 > 解决方案 > 是什么导致我的 Entity Framework Core dbContext 泄漏内存?

问题描述

这涉及到 Microsoft.EntityFrameworkCore.SqlServer,特别是 2.1.14 版本

我在我的服务层中使用 EF,该服务的 API 之一是用于批量操作。所有上下文相关的代码都使用构造函数注入。连接字符串确实启用了 MARS。我像这样注册我的数据库上下文:

services.AddDbContext<ServiceAvailabilityContext>(options => options.UseSqlServer(saConnection));

我已确保所有调用代码都作为 Scoped Task 执行运行。我有一个批处理过程,它同时执行 50 个任务操作,总共 500 个,并且会尝试定期运行 500 个。但是,我注意到随着时间的推移,该服务的堆大小内存消耗只会越来越大。我已经在我的开发机器上运行批处理器和服务的三个演出,并且还尝试运行服务运行时构建。 内存快照 每个服务命令或查询都在 IMediatR IRequestHandler 中运行,为了确保它们被作为 Scoped 调用,我添加了如下管道行为:

var response = await Task.Run(async () =>
        {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                return await next();
            }
        });

调用栈基本上是 Controller -> MediatR Request Handler(context constructor injection) -> Operation。

似乎 EF 只是将所有类型的集合保存在内存中,并且出于某种原因没有释放它们,即使原始上下文已经超出范围,并且所有其他引用也超出了范围。我没有返回 IQueryables,每次检索数据时,我都会立即执行 .ToList() 或 .FirstorDefault() 来完成语句。我什至从未在模型中返回实体对象本身,而是将它们类型转换为 UI 友好对象。我也尝试调用一个方法来打断点,并手动调用 GC.Collect() 没有释放任何内存!

我的主要问题是……为什么?我错过了什么?

标签: .netentity-frameworkasp.net-coreentity-framework-core

解决方案


事实证明,即使 DbContext 与 DI 作用域一起使用,幕后的 ChangeTracker 仍保留对象 HashSet。在不修改对象或分离对象时,我必须更改我的检索语句以使用 AsNoTracking(),而我在调用 SaveChanges() 之后确实对其进行了更改,这消除了内存问题。


推荐阅读