Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Chování sledování určuje, zda Entity Framework Core uchovává informace o instanci entity ve svém sledovači změn. Pokud je entita sledována, všechny změny zjištěné v entitě se zachovají do databáze během SaveChanges. EF Core také opravuje navigační vlastnosti mezi entitami ve výsledku sledovacího dotazu a entitami, které jsou v sledování změn.
Poznámka:
Typy entit bez klíčů se nikdy nesledují. Kdykoli tento článek uvádí typy entit, odkazuje na typy entit, které mají definovaný klíč.
Návod
Ukázku pro tento článek najdete na GitHubu.
Sledování dotazů
Ve výchozím nastavení se dotazy, které vracejí typy entit, sledují. Dotaz sledování znamená, že všechny změny instancí entit jsou uchovávány SaveChanges. V následujícím příkladu je změna hodnocení blogů zjištěna a trvale uložena v databázi během SaveChanges:
var blog = await context.Blogs.SingleOrDefaultAsync(b => b.BlogId == 1);
blog.Rating = 5;
await context.SaveChangesAsync();
Když se výsledky vrátí ve sledovacím dotazu, EF Core zkontroluje, jestli už je entita v kontextu. Pokud EF Core najde existující entitu, vrátí se stejná instance, která může potenciálně použít méně paměti a být rychlejší než dotaz bez sledování. EF Core nepřepíše aktuální a původní hodnoty vlastností entity v záznamu hodnotami z databáze. Pokud se entita v kontextu nenajde, EF Core vytvoří novou instanci entity a připojí ji k kontextu. Výsledky dotazu neobsahují žádnou entitu, která je přidána do kontextu, ale ještě není uložená do databáze.
Dotazy bez sledování
Dotazy bez sledování jsou užitečné, když se výsledky používají ve scénáři jen pro čtení. Obvykle jsou rychlejší, protože není potřeba nastavovat informace o sledování změn. Pokud entity načtené z databáze nemusí být aktualizovány, měl by se použít dotaz bez sledování. Jednotlivé dotazy je možné nastavit tak, aby nebyly žádné sledování. Dotaz bez sledování také poskytuje výsledky na základě toho, co je v databázi, a ignoruje všechny místní změny nebo přidané entity.
var blogs = await context.Blogs
.AsNoTracking()
.ToListAsync();
Výchozí chování sledování lze změnit na úrovni kontextové instance:
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var blogs = await context.Blogs.ToListAsync();
Následující část vysvětluje, kdy dotaz bez sledování může být méně efektivní než sledovací dotaz.
Rozlišení identity
Vzhledem k tomu, že sledovací dotaz používá sledování změn, EF Core provádí rozlišení identity v rámci sledovacího dotazu. Při materializaci entity vrátí EF Core stejnou instanci entity z sledování změn, pokud je již sledována. Pokud výsledek obsahuje stejnou entitu vícekrát, vrátí se stejná instance pro každý výskyt. Dotazy bez sledování:
- Nepoužívejte sledování změn a nedělejte rozpoznání identity.
- Vrátí novou instanci entity i v případě, že stejná entita je ve výsledku vícekrát obsažena.
Sledování a sledování bez sledování je možné kombinovat ve stejném dotazu. To znamená, že můžete mít dotaz bez sledování, který ve výsledcích provádí rozlišení identity. Stejně jako AsNoTracking dotazovatelný operátor jsme přidali další operátor AsNoTrackingWithIdentityResolution<TEntity>(IQueryable<TEntity>). Do výčtu QueryTrackingBehavior se přidává také asociovaná položka. Pokud je dotaz na použití řešení identity nakonfigurován bez sledování změn, při generování výsledků dotazu se na pozadí použije samostatný sledovač změn, aby byla každá instance materializována pouze jednou. Protože se tento sledovač změn liší od sledovače změn v kontextu, výsledky nejsou sledovány kontextem. Jakmile se dotaz plně vyčíslí, sledování změn přestane být v rozsahu a uvolňování paměti podle potřeby.
var blogs = await context.Blogs
.AsNoTrackingWithIdentityResolution()
.ToListAsync();
Konfigurace výchozího chování sledování
Pokud zjistíte, že měníte chování sledování u mnoha dotazů, můžete místo toho změnit výchozí nastavení:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying.Tracking;Trusted_Connection=True;ConnectRetryCount=0")
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}
Tím se všechny vaše dotazy ve výchozím nastavení nesledují. Stále můžete přidat AsTracking , abyste mohli provádět sledování konkrétních dotazů.
Sledování a vlastní výpočty
I když typ výsledku dotazu není typem entity, EF Core bude ve výchozím nastavení sledovat typy entit obsažených ve výsledku. V následujícím dotazu, který vrátí anonymní typ, budou sledovány Blog instance v sadě výsledků.
var blog = context.Blogs
.Select(
b =>
new { Blog = b, PostCount = b.Posts.Count() });
Pokud sada výsledků obsahuje typy entit pocházející ze složení LINQ, EF Core je bude sledovat.
var blog = context.Blogs
.Select(
b =>
new { Blog = b, Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault() });
Pokud sada výsledků neobsahuje žádné typy entit, neprovádí se žádné sledování. V následujícím dotazu vrátíme anonymní typ s některými hodnotami z entity (ale žádné instance skutečného typu entity). Neexistují žádné sledované entity přicházející z dotazu.
var blog = context.Blogs
.Select(
b =>
new { Id = b.BlogId, b.Url });
EF Core podporuje vyhodnocování klientů v projekci nejvyšší úrovně. Pokud EF Core materializuje instanci entity pro vyhodnocení klienta, bude sledována. Vzhledem k tomu, že předáváme blog entity do metody StandardizeURLklienta, EF Core také bude sledovat instance blogu.
var blogs = await context.Blogs
.OrderByDescending(blog => blog.Rating)
.Select(
blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog) })
.ToListAsync();
public static string StandardizeUrl(Blog blog)
{
var url = blog.Url.ToLower();
if (!url.StartsWith("http://"))
{
url = string.Concat("http://", url);
}
return url;
}
EF Core nesleduje instance entit bez klíčů obsažené ve výsledku. EF Core ale sleduje všechny ostatní instance typů entit s klíčem podle výše uvedených pravidel.
Předchozí verze
Před verzí 3.0 měla EF Core určité rozdíly v tom, jak bylo sledování provedeno. Významné rozdíly jsou následující:
Jak je vysvětleno na stránce Hodnocení klienta a serveru , podporuje ef Core vyhodnocení klienta v jakékoli části dotazu před verzí 3.0. Vyhodnocení klienta způsobilo materializaci entit, které nebyly součástí výsledku. Ef Core proto analyzoval výsledek, aby zjistil, co se má sledovat. Tento návrh měl určité rozdíly:
Vyhodnocení klienta v projekci, které vedlo k materializaci, ale nevrátilo materializovanou instanci entity, nebylo sledováno. Následující příklad nesledoval
blogentity.var blogs = await context.Blogs .OrderByDescending(blog => blog.Rating) .Select( blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog) }) .ToListAsync();EF Core v určitých případech nesledoval objekty přicházející z kompozice LINQ. Následující příklad nesledoval
Post.var blog = context.Blogs .Select( b => new { Blog = b, Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault() });
Pokaždé, když výsledky dotazu obsahovaly typy entit bez klíčů, celý dotaz se neprosledoval. To znamená, že typy entit s klíči, které jsou ve výsledku, také nebyly sledovány.
EF Core slouží k řešení identit v dotazech bez sledování. Pomocí slabých odkazů bylo možné sledovat entity, které už byly vráceny. Pokud tedy sada výsledků obsahovala stejnou entitu vícekrát, získáte stejnou instanci pro každý výskyt. I když předchozí výsledek se stejnou identitou vyplul z oboru a byl posbíraný systémem uvolňování paměti, EF Core vrátil novou instanci.