【发布时间】:2020-02-27 22:37:51
【问题描述】:
这涉及到 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()!
我的主要问题是......为什么?我错过了什么?
【问题讨论】:
-
调查这些集合是通过什么路径保存在内存中的,您可能会知道原因。
-
谢谢埃德。我听从了您的建议,并意识到它是附加对象的 HashSet 和 ChangeTrackers。我只是不认为它会那样工作....
标签: .net entity-framework asp.net-core entity-framework-core