【问题标题】:EF Core increasing memory usage in insert loopEF Core 增加插入循环中的内存使用量
【发布时间】:2021-03-26 08:03:01
【问题描述】:

我有一个长时间运行的应用程序,它下载一些数据并将它们批量插入到 sql server 数据库中。 我已禁用跟踪并设置AutoDetectChangesEnabled = false

        _context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        _context.ChangeTracker.AutoDetectChangesEnabled = false;
        while ((data = getData()) != null)
        {
            await _context.MyTable.AddRangeAsync(data);
            await _context.SaveChangesAsync();
        }

此代码开始快速插入数据,但几个小时后,我可以看到长时间的停顿并且使用的内存增长(许多 GB)。我怀疑 EF 核心在内存中保存了一份数据。

有什么方法可以禁用此行为?

我用这个原始的 sql 代码替换了在一个命令中插入多个项目并且内存根本没有增加。

        while ((data = getData()) != null)
        {
            string cmd = $"INSERT INTO dbo.Table(name1,name2) VALUES "
                       + string.Join(",", data.Select(x => $"('{x.name1}', '{x.name2}')"));
            _context.Database.ExecuteSqlRaw(cmd);
        }

我想使用非原始版本,但我是否遗漏了一些关于内存的内容?

【问题讨论】:

  • EF Contexts 将每个实体添加到上下文中,因此上下文分配的内存变得更大。在批量插入场景中,建议分批工作,处理和重新创建上下文。此外,您可以使用一些第三方批量插入 nuget 包。他们通常在内部使用纯 SQL 来进行插入,但效果很好,而且对您来说它是透明的。
  • @Pepelui360 谢谢,我希望有一些设置'不要让每个实体都添加到上下文中'。
  • 在我切换到 Linq2db 之前,我也遇到了这个问题。 Linq2db 比 EFCore 更快更好的内存管理。

标签: c# performance entity-framework-core bulkinsert


【解决方案1】:

取决于你如何生成上下文 ->

请求使用范围或“使用”,因此您在每次插入后垃圾收集 EF-Core 实例。这应该可以解决您的内存“泄漏”问题。

using(_context = new context())
{
   await _context.MyTable.AddRangeAsync(data);
   await _context.SaveChangesAsync();
}

或者如果您使用 DI:使用 IServiceFactory 接口,

using (var scope = scopeFactory.CreateScope())
{
   var context = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
   await context.MyTable.AddRangeAsync(data);
   await context.SaveChangesAsync();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多