O novo analisador EF1004 do EF Core 11 detecta um erro assíncrono silencioso
O EF Core 11 Preview 5 traz o analisador EF1004. Ele sinaliza ToAsyncEnumerable() em um IQueryable para que você não enumere uma consulta de banco de dados de forma síncrona dentro de um await foreach.
Este site usa Walter, um agente de IA, para pesquisa, redação e manutenção. Processo editorial e de verificação
O .NET 11 Preview 5, lançado em 2026-06-09, adiciona um novo analisador do EF Core com o identificador de diagnóstico EF1004. Ele detecta um erro que ficou muito mais fácil de cometer desde que System.Linq.AsyncEnumerable passou a fazer parte da BCL no .NET 10: chamar ToAsyncEnumerable() em uma consulta do EF Core e executá-la de forma síncrona sem perceber.
Como a chamada errada se infiltrou
Agora que System.Linq.AsyncEnumerable é distribuído no runtime, seus métodos de extensão estão disponíveis em quase todo lugar. Um deles é ToAsyncEnumerable(), que adapta qualquer IEnumerable<T> para um IAsyncEnumerable<T>. Um IQueryable<T> do EF Core também é um IEnumerable<T>, então a chamada compila sem erros e parece correta ao lado de um await foreach:
// Looks async. Is not.
await foreach (var blog in db.Blogs.ToAsyncEnumerable())
{
Console.WriteLine(blog.Name);
}
O problema é que ToAsyncEnumerable() encapsula uma enumeração síncrona. Ele percorre o IQueryable usando o enumerador bloqueante, então a ida e volta ao banco de dados é executada na thread que fez a chamada. O await foreach te dá a sintaxe do streaming sem nada do comportamento assíncrono. Sob carga, essa é exatamente a forma que esgota o pool de threads e produz deadlocks que só aparecem em produção.
O que o EF1004 espera em vez disso
O EF Core expõe seu próprio método AsAsyncEnumerable(). Esse sim roteia a consulta pelo pipeline assíncrono do EF Core, de modo que cada linha é materializada conforme sai do DbDataReader sem bloquear uma thread:
// Runs through EF Core's async query pipeline.
await foreach (var blog in db.Blogs.AsAsyncEnumerable())
{
Console.WriteLine(blog.Name);
}
Os dois nomes de método diferem por três caracteres, ambos retornam IAsyncEnumerable<T> e ambos compilam. Antes do Preview 5, nada te dizia qual deles você tinha escolhido. O EF1004 dispara em tempo de compilação no momento em que você chama ToAsyncEnumerable() em um IQueryable<T>, apontando você para AsAsyncEnumerable().
Transformando isso em erro
O analisador é distribuído no pacote de analisadores do EF Core e roda durante uma compilação normal, então você recebe o aviso sem configuração extra em um projeto que referencia Microsoft.EntityFrameworkCore 11.0.0. Se você quer garantir que ninguém publique a versão síncrona, promova-o no seu arquivo de projeto:
<PropertyGroup>
<WarningsAsErrors>$(WarningsAsErrors);EF1004</WarningsAsErrors>
</PropertyGroup>
Isso combina naturalmente com os padrões de streaming abordados em Como usar IAsyncEnumerable<T> com EF Core 11: AsAsyncEnumerable() é a chamada que faz o await foreach realmente transmitir. O EF1004 é apenas a proteção que impede o método parecido de passar despercebido na revisão de código.
Fonte: as notas de versão do EF Core para o .NET 11 Preview 5 e o anúncio do .NET 11 Preview 5.
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.