У меня есть запрос к моей базе данных, использующий EF Core 3.1 с Postgresql, который иногда может возвращать большой набор результатов в зависимости от запрошенных параметров. Я использую Asyn c Enumerable для потоковой передачи результатов, что иногда может занять более минуты:
try
{
IAsyncEnumerable<Entity> ae = ctxt.Entity.Where(e => e.Value > 5).AsAsyncEnumerable();
await foreach(Entity e in ae.ConfigureAwait(false))
{
//Do some work on each one here that could potentially throw an exception
}
}
catch(Exception ex)
{
//This code can take over a minute after the exception is thrown to begin executing
}
Затем я избавился от await foreach
l oop, чтобы получить лучшую идею что происходило:
IAsyncEnumerable<Entity> ae = ctxt.Entity.Where(e => e.Value > 5).AsAsyncEnumerable();
var enumerator = ae.GetAsyncEnumerator();
await enumerator.MoveNextAsync();
await enumerator.DisposeAsync();
Console.WriteLline("Done Disposing");
И обнаружил, что DisposeAsync
звонок был там, где проводилось время. Я вернулся к await foreach
и смог подтвердить, что использование break
внутри l oop показывало то же поведение.
Затем я попытался создать не-ef IAsyncEnumerable
, чтобы увидеть, это поведение было связано с Entity Frameowork или нет.
private async IAsyncEnumerable<int> IntEnumerator()
{
await Task.Delay(0).ConfigureAwait(false);
for(int i = 0; i < int.MaxValue; i++)
{
yield return i;
}
}
Используя этот код, Dispose был мгновенным.
IAsyncEnumerable<int> ae = IntEnumerator();
var enumerator = ae.GetAsyncEnumerator();
await enumerator.MoveNextAsync();
await enumerator.DisposeAsync();
Console.WriteLline("Done Disposing");
Это заставляет меня поверить, что проблема определена c для Ядро EF, но я не уверен, является ли это ошибкой в их реализации, или я делаю что-то не так. Кто-нибудь еще видел что-то подобное и нашел решение?
Я хотел проверить здесь, прежде чем открывать проблему на странице EF github.