Nic*_*cer 7 c# memory-leaks entity-framework-core .net-core
我们看到内存资源没有被释放:
使用 .NET Core 的以下代码:
class Program
{
static void Main(string[] args)
{
while (true) {
var testRunner = new TestRunner();
testRunner.RunTest();
}
}
}
public class TestRunner {
public void RunTest() {
using (var context = new EasyMwsContext()) {
var result = context.FeedSubmissionEntries.Where(fse => TestPredicate(fse)).ToList();
}
}
public bool TestPredicate(FeedSubmissionEntry e) {
return e.AmazonRegion == AmazonRegion.Europe && e.MerchantId == "1234";
}
}
Run Code Online (Sandbox Code Playgroud)
如果我删除测试谓词,.Where
我会得到预期的直线,使用谓词,内存将继续无限期地增加。
因此,虽然我可以解决问题,但我想了解发生了什么?
编辑:
将该行更改为:
public void RunTest() {
using (var context = new EasyMwsContext()) {
var result = context.FeedSubmissionEntries.ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
所以我也不认为这是由于客户端评估造成的?
编辑2:
使用 EF Core 2.1.4
编辑3:
添加了保留图,似乎是 EF Core 的问题?
我怀疑罪魁祸首不是内存泄漏,而是 EF Core客户端评估的一个相当不幸的补充。与 LINQ-to-SQL 一样,当遇到无法转换为 SQL 的 lambda/函数时,EF Core 将创建一个更简单的查询来读取更多数据并在客户端上评估该函数。
在您的情况下,EF Core 无法知道TestPredicate
是什么,因此它将读取内存中的每条记录,然后尝试过滤数据。
顺便说一句,这就是2018 年 10 月 4 日上星期四 SO 迁移到 EF Core 时发生的情况。查询返回的不是几十行,而是……5200 万行:
var answers = db.Posts
.Where(p => grp.Select(g=>g.PostId).Contains(p.Id))
...
.ToList();
Run Code Online (Sandbox Code Playgroud)
客户评估是可选的,但默认情况下处于启用状态。每次执行客户端评估时,EF Core 都会记录一条警告,但如果您尚未配置 EF Core 日志记录,这将无济于事。
安全的解决方案是禁用客户端评估,如文档的可选行为:抛出客户端评估异常部分所示,无论是在每个上下文的OnConfiguring
方法中还是在 Startup.cs 配置中全局:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(...)
.ConfigureWarnings(warnings =>
warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}
Run Code Online (Sandbox Code Playgroud)
更新
找出泄漏的快速方法是在“诊断”窗口中拍摄两个内存快照,并检查创建了哪些新对象以及它们使用了多少内存。很有可能是客户评价出了问题。
小智 4
我最终遇到了同样的问题。一旦我知道问题是什么,我就可以在 EntityFrameworkCore 存储库中找到它的错误报告。
简而言之,当您在 an 中包含实例方法时,IQueryable
它会被缓存,并且即使在您的上下文被释放后,这些方法也不会被释放。
目前看来解决该问题并没有取得太大进展。我会密切关注它,但现在我相信避免内存泄漏的最佳选择是:
IQueryable
IQueryable
为list
with ToList()
(如果您尝试限制数据库查询的结果,则不理想)static
限制内存堆积量 归档时间: |
|
查看次数: |
9818 次 |
最近记录: |