EF Core  -  Usando AsNoTracking com Identity Resolution


 Hoje veremos as consequências em usar AsNoTracking com o recurso Identity Resolution disponível a partir da  EF Core 5.0.

Eu já apresentei o conceito Identity Resolution neste artigo, mas de forma bem resumida, o Identity Resolution é usado pelo EF Core para manter uma única instância de uma determinada chave primária.


O que é o AsNoTracking ?

O recurso AsNoTracking é uma opção sugerida para tornar as consultas mais rápidas, pois usando este recurso  as consultas não passam pela lógica de rastreamento de entidade, e o EF Core apenas vai ao banco de dados e traz os dados para você.

Toda vez que sua aplicação realiza uma consulta, o EF core verifica se o contexto já está rastreando os objetos necessários, em caso positivo, o EF Core retornará dados do contexto. Se o contexto não contiver essas entidades, o EF core fará uma consulta ao banco de dados e os dados retornados pelo banco de dados são usados para criar novas instâncias das respectivas entidades e essas entidades são então anexadas ao contexto.

Exemplo de código usando AsNoTracking:

       using (PaisDbContext context = new PaisDbContext())
        {
                WriteLine("-------------Desbilitando o rastreamento ---------------");

                var paises = context.Paises.AsNoTracking().ToList();

                foreach (var pais in paises)
                {
                    WriteLine($"{pais.Id}\t{pais.Nome}");
                }
                ReadLine();
        }

Nota: Baseado no projeto criado no artigo : Usando AsNoTracking

Vamos detalhar um pouco mais o funcionamento do rastreamento das entidades e de como o AsNoTracking atua.

As consultas realizadas pelo EF Core no banco de dados retornam tipos de entidade, e, por padrão, essas consultas são consultas de rastreamento pois o rastreamento esta habilitado por padrão no EF Core.

Todas as operações realizadas em uma entidade que está sendo rastreada são mantidas pelo contexto, e, as alterações não são salvas no banco de dados até que o método SaveChanges ou SaveChangesAsync seja chamado.

Assim, toda vez que a aplicação faz uma consulta, o EF core verifica se o contexto já está rastreando os objetos necessários, e, se o contexto estiver fazendo o rastreamento, o EF core retornará os dados do contexto. Portanto, os dados são retornados pelo EF core sem realmente consultar o banco de dados.

Se o contexto não contiver essas entidades, o EF core fará uma consulta ao banco de dados e  os dados retornados pelo banco de dados são usados para criar novas instâncias das respectivas entidades. Essas entidades são então anexadas ao contexto.

Sem rastreamento significa Sem Identity Resolution

Quando o rastreamento está habilitado, o EF Core usa o Identity Resolution ou resolução de identidade para manter apenas uma única instância de uma determinada chave primária. Mas quando o AsNoTracking é usado, a resolução de identidade não é usada pelo EF Core.

O que isto significa ?

Digamos que os resultados retornados pela consulta contenham a chave primária repetida várias vezes.

Se o rastreamento estiver ativado, uma única chave primária criará apenas um único objeto e o anexará ao contexto.

Se o rastreamento NÃO estiver habilitado, para cada linha, um novo objeto será criado.

Portanto, mesmo que a chave primária seja a mesma, o EF Core criará vários objetos da entidade.

Sentiu o drama !!!!

Usando AsNoTracking com Identity Resolution

No entanto isso mudou a partir do EF Core 5.0.

Antes do EF Core 5.0, não havia como habilitar a resolução de identidade com AsNoTrakcing.

Mas agora, a partir do EF Core 5.0, existe uma API adicional que pode ser usada para habilitar AsNoTracking e usar Identity Resolution ou resolução de identidade.

using (PaisDbContext context = new PaisDbContext())
{

Console.WriteLine("-------------Desabilitando o rastreamento ---------------");

    var paises = context.Paises.AsNoTrackingWithIdentityResolution().ToList();

    foreach (var pais in paises)
    {
       Console.WriteLine($"{pais.Id}\t{pais.Nome}");
    }
    Console.ReadLine();
}

Este código mostra o uso do novo recurso AsNoTrackingWithIdentityResolution.

Aqui, com a API AsNoTrackingWithIdentityResolution, a resolução de identidade é habilitada, mas não habilita o rastreamento de entidades.

Portanto, quando uma consulta retorna um conjunto de resultados contendo várias linhas com o mesmo valor de chave primária, o EF Core cria um único objeto para um determinado valor de chave primária.

Mas esses objetos não são adicionados para rastreamento.

Essa opção pode ser útil em alguns cenários para reduzir o número de objetos criados (otimizando assim o uso da memória).

Isso vem resolver o problema de consultas quando temos um relacionamento entre as entidades do tipo um para muitos.

Aguarde que veremos qual problema esse novo recurso resolve neste cenário.

Pegue o projeto aqui:  EFCoreIdentityResolution.zip

E estamos conversados...

"Orem também para que sejamos libertos dos homens perversos e maus, pois a fé não é de todos.
Mas o Senhor é fiel; ele os fortalecerá e os guardará do Maligno."
2 Tessalonicenses 3:2,3

Referências:


José Carlos Macoratti