【问题标题】:EF Core context not disposing of change tracking entitiesEF Core 上下文不处理更改跟踪实体
【发布时间】:2019-08-20 17:08:40
【问题描述】:

使用 EF Core 2.1 插入 135k 条记录。一旦请求完成,我希望上下文会被处理掉,ChangeTracking 实体也会随之被清除,但是,它会保留所有 135k 记录并在此过程中使用大量内存。

我们正在使用 ASP.NET Core 2.1 并从 DI 容器注入 EF 上下文。由于 DI 容器应该在请求结束时处理作用域上下文,它不应该保留这些值。即使在控制器末尾手动调用 dispose 似乎也不会影响更改跟踪实体。

以下是请求完成后内存使用情况的堆视图的输出。深入研究路径,我看到了很多 EF Core 类,并且奇怪地看到了不同实体的 EntityQueryable 实例(SystemInvoicePendingItem)。


上下文正在Startup.cs中注册:

services.AddDbContext<EFContext>(options => options.UseMySql(
  GetDBConnectionString()
));

【问题讨论】:

  • DBContext 注册的服务生命周期是多少?
  • 你能显示将 DBContext 注册到容器的代码吗?
  • @GaryStewart,添加了它。我们使用的是默认方法,它应该是一个作用域生命周期。
  • 我问的原因是堆上的对象会一直留在那里,直到它们被垃圾回收。垃圾收集是非确定性的,这意味着它在 .net 框架确定需要执行时发生。当垃圾收集发生时,堆上的对象也可能不会被释放,这取决于它们是哪一代。因此,即使请求已完成并且 DbContext 实例已被释放,这 135,000 个实例仍可能保留在堆上。您应该看到的是通过新的DbContext 实例在不同的或新的请求上对这135,000 个实例的引用。
  • GC.Collect 在没有更多引用之前不会做任何事情(因此在同一个请求中调用它没有影响,因为该请求的 DI 框架中仍然存在引用),即便如此如果对象在生成中被提升或有一个未决的终结器,则它们可以存活。

标签: c# entity-framework asp.net-core .net-core entity-framework-core


【解决方案1】:

似乎是一个关于: How should I manage DbContext Lifetime in MVC Core?

对于更改跟踪,它默认启用,并在您处理上下文时被删除。但是,您也可以通过将 DbContext 的 AutoDetectChangesEnabled 属性设置为 false 来禁用更改跟踪

context.Configuration.AutoDetectChangesEnabled = false;

此外,当您插入 +100k 项时,出于性能和内存原因,您应该分批执行此操作,例如 2k。

【讨论】:

  • 你在哪里找到 DbContext 的配置?据我所知-到目前为止-您应该使用更改跟踪:link 另请参阅:link
  • 具体文档:link
【解决方案2】:

您可以在您的类中正确实现 IDispose 接口,并管理不再使用时如何销毁该类,实现该接口并使用 Dispose 模式。

阅读本文档:https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose

【讨论】:

  • 尝试覆盖 dbcontext 的 dispose,然后实施正确的 Dispose 模式。 public void Dispose() { // 释放非托管资源。处置(真); // 禁止终结。 GC.SuppressFinalize(this); }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 2021-11-19
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 2019-01-10
相关资源
最近更新 更多