Я знаю, что в EF6 было проделано много работы для поддержки асинхронных операций, таких как CountAsync, но я не могу отменить простой запрос. Вот история.
У меня есть запрос, который возвращает 4,5 миллиона строк. Мне нужно обработать каждую строку, но я не могу удержать их все в памяти. 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);
Это не поглощает память, и я могу отменить его, но отмена требует вечности, чтобы ответить, и есть несколько неприятных исключений, потому что я вытаскиваю ковер.
Что мне здесь не хватает?
foreach (var row in context.TableX.AsNoTracking().WithCancellation(token))
. Это сохраняет модель вытягивания.ForEachAsync
- это push, который менее компонуем. Например, вы больше не можете обрабатывать результаты какIEnumerable
. - person usr   schedule 30.04.2016