如何使用 AsNoTracking 和 CancellationToken 查询大型 DbSet

How to query a large DbSet with AsNoTracking and a CancellationToken

我知道在 EF6 中做了很多工作来支持 CountAsync 等异步操作,但我似乎无法取消简单的查询。这是故事。

我有一个查询 returns 450 万行。我需要处理每一行,但我不能将它们全部保存在内存中。 EF6 好心让我这样做:

foreach (var row in context.TableX.AsNoTracking())
{
...process each row
}

这很好用并且占用的内存很少,但是取消起来不是很容易。我试过这种愚蠢的做法:

foreach (var row in context.TableX.AsNoTracking().ToListAsync(token).Result)
{
...process each row
}

当然,这会尝试将整个查询加载到一个 List<> 中,该列表在加载所有行之前很久就崩溃了。值得庆幸的是,它对取消非常敏感。 :)

我最接近的是像这样包装整个混乱:

Task.Run(() => DoQuery(), token);

这不会占用内存,我 可以 取消它,但取消需要永远响应,并且有一些讨厌的例外,因为我正在拉地毯。

我在这里错过了什么?

你可以这样做:

public async Task DoQuery(CancellationToken token) {
    await ctx.TableX.AsNoTracking().ForEachAsync(row =>
    {
         // process here
    }, token);
}