EF 6 连接池和存储的查询字符串 RAM 泄漏
Posted
技术标签:
【中文标题】EF 6 连接池和存储的查询字符串 RAM 泄漏【英文标题】:EF 6 Connection pool and stored query strings RAM leak 【发布时间】:2020-07-01 02:09:41 【问题描述】:我有 2 个问题。
第一个是连接池和(OracleConnectionImpl)随着时间的推移稳步增长,直到它达到内存不足异常。正如您在图片上看到的,它在运行 3-4 小时后有 90 MB。
我到处都在使用短暂的上下文,但它会不断增长并且永远不会自行清除。有什么办法可以清除吗?
第二个是 EF 随着时间的推移存储了太多重复的字符串查询。 它主要存储来自 .Reload() 函数的那些,因为它没有参数化,它将 ID 硬编码到查询中。 然后还有像“ID”这样的字符串,它被缓存在 2947x 的某个地方。
.Reload() 函数有什么方法可以使其参数化,或者清除所有存储的字符串?
此应用每隔几秒钟刷新一次仓库作业和托盘,以使其与所有机器保持同步,由于 WPF 绑定,我不知道比 .Reload() 更好的方法。
编辑 1
我有一个简单的辅助函数,可以一次重新加载许多实体,甚至是一个扩展。将它作为对象传递并不重要,因为即使是最后一个示例,同样的问题仍然存在。
public static void ReloadEntities(bool dispatch, params IEnumerable<object>[] entities)
using (var ctx = new eWMSEntities())
if (dispatch)
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
entities.SelectMany(x => x.Select(s => s)).ToList().ForEach(entity =>
ctx.Set(entity.GetType()).Attach(entity);
ctx.Entry(entity).Reload();
ctx.Entry(entity).State = EntityState.Detached;
);
, null);
else
entities.SelectMany(x => x.Select(s => s)).ToList().ForEach(entity =>
ctx.Set(entity.GetType()).Attach(entity);
ctx.Entry(entity).Reload();
ctx.Entry(entity).State = EntityState.Detached;
);
ctx.Dispose();
public static void ReloadEntity(this object entity, bool dispatch)
using (var ctx = new eWMSEntities())
ctx.Set(entity.GetType()).Attach(entity);
if (dispatch)
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, (SendOrPostCallback)delegate
ctx.Entry(entity).Reload();
, null);
else
ctx.Entry(entity).Reload();
ctx.Entry(entity).State = EntityState.Detached;
ctx.Dispose();
while (true && JobLines.Contains(line))
using (var ctx = new eWMSEntities())
ctx.T_JOB_LINES.attach(line);
ctx.entry(line).Reload();
await Task.Delay(3000);
这是运行 3 天后的快照
【问题讨论】:
这将有助于查看几个典型的代码示例,其中您正在加载视图并执行更新/插入以及您认为是短期上下文的内容。 @StevePy 嗨,我添加了如何重新加载实体的示例代码。在这个特定的程序中,我没有做任何插入或更新。我只是将数据保持在线以显示它。 如果它是一次性的(因为您正在“使用”ctx),为什么必须强制使用 ctx.dispose()?使用结束时应该优雅地处理它。 EF6 不进行批量操作。我认为这就是为什么您在重新加载时会看到很多重复的字符串。你可以试试EF Plus。如果您的任何查询使用 Skip、Take 或 Contains,您应该看到这个 answer。至于连接池,请验证服务器中允许的最大连接数。 @KevinCook 这只是解决问题的绝望尝试。 【参考方案1】:我不推荐,但如果没有其他解决方案... 也许你可以试试
GC.Collect();
让系统强制收集你记忆中不重要的东西。
【讨论】:
你好,谢谢你的想法,但我已经尝试强制 GC,但它现在运行良好。只是 EF 没有得到清理。 我发现关于干净的空值和重复的东西看起来很相似。也许这会有所帮助...link【参考方案2】:使用“工作单元”模式 - 它可以解决很多问题。我没有找到 WPF,但找到了 ASP.NET MVC
【讨论】:
感谢您的参考,但它并没有真正的帮助以上是关于EF 6 连接池和存储的查询字符串 RAM 泄漏的主要内容,如果未能解决你的问题,请参考以下文章