- 1 - Tracking vs NoTracking
- 2 - Resolução de identidade
- 3 - Desabilitando rastreamento de consultas
- 4 - Consulta com tipo anônimo rastreada
- 5 - Consultas projetadas
É a funcionalidade padrão do EF.
var cursos = db.Cursos.Where(x => x.Id < 10).ToList();
A instância de cada registro é marcada com Unchanged dentro do seu DbContext.
Com isso o EF é capaz de detectar as instâncias que foram manipuladas.
var cursos = db
.Cursos
.AsNoTracking()
.Where(x => x.Id < 10)
.ToList();
Simplesmente materializa cada entidade.
Dependendo da quantidade de registros que você busca do banco de dados, você pode ter uma degradação de desempenho.
Resultado da analise:
Rastreada
└── Departamentos 1 instância 40 bytes
Não Rastreada
└── Departamentos 100 instâncias 4000 bytes
Com resolução de identidade
└── Departamentos 1 instância 40 bytes
using var db = new ApplicationContext();
var funcionarios = db
.Funcionarios
.AsNoTrackingWithIdentityResolution()
.Include(x => x.Departamento)
.ToList();
Por padrão, todas as consultas são rastreadas.
A três cenários de configuração
// Por default é AsTracking
db.Funcionarios
// Redudante pois por padrão todas as consultas são rastreadas
//.AsTracking()
.Include(x => x.Departamento)
.ToList();
// Não rastrear
db.Funcionarios
.AsNoTracking()
.Include(x => x.Departamento)
.ToList();
// Resolução de identidade
db.Funcionarios
.AsNoTrackingWithIdentityResolution()
.Include(x => x.Departamento)
.ToList();
No DbContext é possível customizar o comportamento através do Enum: QueryTrackingBehavior.
optionsBuilder
.UseSqlServer(stringDeConexao)
.EnableSensitiveDataLogging()
.LogTo(Console.WriteLine, LogLevel.Information)
// Parametros: TrackAll (Default), NoTracking e NoTrackingWithIdentityResolution
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTrackingWithIdentityResolution)
Para habilitar em uma determinada consulta
private static void ConsultaCustomizada1()
{
using var db = new ApplicationContext();
// Foi definido do DbContext NoTrackingWithIdentityResolution
// como comportamento padrão
var funcionarios = db
.Funcionarios
// Irei rastrear essa consulta
.AsTracking()
.Include(x => x.Departamento)
.ToList();
}
private static void ConsultaCustomizada2()
{
using var db = new ApplicationContext();
// Em tempo de execução dessa instancia, irei rastrear todas as consultas,
// na instância do seu contexto
db.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll;
var funcionarios = db
.Funcionarios
.Include(x => x.Departamento)
.ToList();
}
Consulta projetadas anonimas também são rastreadas pelo EF, com isso você pode atualizar informações normalmente.
using var db = new ApplicationContext();
var departamentos = db.Departamentos
.Include(x => x.Funcionarios)
.Select(x => new
{
Departamento = x,
TotalFuncionarios = x.Funcionarios.Count()
})
.ToList();
departamentos[0].Departamento.Descricao = "Departamento teste atualizado";
db.SaveChanges();
As consultas projetadas tem uma melhor performance dependendo do cenário
private static void ComProjecao()
{
using var db = new ApplicationContext();
var comProjecao = db.Departamentos
.Select(x => x.Descricao)
.ToArray();
var memoriaComProjecao = (System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024) + " MB";
Console.WriteLine($"Total de memoria utilizada: {memoriaComProjecao}");
}
private static void SemProjecao()
{
using var db = new ApplicationContext();
var semProjecao = db.Departamentos.ToArray();
var memoriaSemProjecao = (System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024) + " MB";
Console.WriteLine($"Total de memoria utilizada: {memoriaSemProjecao}");
}