Entity Framework Core – AsNoTracking() v skratke
Pri práci s Entity Framework Core hrá dôležitú úlohu Change Tracker.
Štandardne platí, že keď načítaš entity z databázy, EF Core si ich začne sledovať –
teda vie, čo sa zmenilo a čo má zapísať späť cez SaveChanges().
Nie vždy to ale chceš. Pri čisto čítacích dotazoch je sledovanie zbytočné a spomaľuje aplikáciu. Na to slúži AsNoTracking().
1. Čo robí AsNoTracking()
Metóda AsNoTracking() vypne sledovanie entít pre daný LINQ dotaz.
Výsledkom je:
- nižšia spotreba pamäte
- rýchlejšie dotazy (najmä pri väčšom množstve dát)
- ale – EF Core nebude vedieť tieto entity neskôr automaticky uložiť
// štandardný dotaz – trackovanie zapnuté
var users = await _db.Users.ToListAsync();
// dotaz bez trackovania
var usersReadOnly = await _db.Users
.AsNoTracking()
.ToListAsync();
usersReadOnly sú ideálne na zobrazenie v UI, reporty, exporty a všetko, kde
ich už nebudeš spätne upravovať a ukladať.
2. Kedy AsNoTracking() použiť
- read-only API endpointy (GET /list, GET /detail)
- reporty, dashboardy, štatistiky
- background joby, ktoré iba čítajú
Ak vieš, že objekt nebudeš upravovať a volať naň SaveChanges(),
použi AsNoTracking() ako predvolenú voľbu.
3. AsNoTrackingWithIdentityResolution()
EF Core má aj variant:
var users = await _db.Users
.Include(u => u.Roles)
.AsNoTrackingWithIdentityResolution()
.ToListAsync();
Táto verzia:
- stále netrackuje entity (nebudú sa ukladať)
- ale zabezpečí, že tá istá entita v grafe bude v pamäti reprezentovaná jednou inštanciou (identity resolution)
Hodí sa pri zložitejších grafoch s viacerými Include(), kde chceš konzistentné
referencie, ale stále read-only dotazy.
4. Globálne nastavenie – QueryTrackingBehavior
Ak máš veľa read-only dotazov, môžeš nastaviť správanie globálne v DbContext:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}
// ...
}
Tak budú všetky dotazy defaultne bez trackovania a tam, kde potrebuješ zapisovať zmeny, si tracking zapneš ručne:
var user = await _db.Users
.AsTracking()
.FirstOrDefaultAsync(u => u.Id == id);
5. Zhrnutie
- AsNoTracking() – rýchlejšie, ľahšie, vhodné pre read-only scenáre.
- AsNoTrackingWithIdentityResolution() – read-only, ale s riešením identity pre komplexné grafoy.
- AsTracking() – explicitné zapnutie sledovania, keď potrebuješ zapisovať.
- QueryTrackingBehavior – možnosť nastaviť default (napr. NoTracking) pre celý DbContext.
Praktický tip: v moderných API aplikáciách je často dobrý vzor: všetky query sú NoTracking, a tracking používaš len tam, kde naozaj meníš stav a ukladáš zmeny.