Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of mappen te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen om mappen te wijzigen.
Tracering van gedrag bepaalt of Entity Framework Core informatie over een entiteitsexemplaar in zijn wijzigingentracker bijhoudt. Als een entiteit wordt bijgehouden, worden eventuele wijzigingen die in de entiteit zijn gedetecteerd, tijdens SaveChanges in de database bewaard. EF Core corrigeert ook navigatie-eigenschappen tussen de entiteiten in een resultaat van een traceringsquery en de entiteiten die zich in de wijzigingentracker bevinden.
Opmerking
Sleutelloze entiteitstypen worden nooit bijgehouden. Waar in dit artikel ook entiteitstypen worden vermeld, wordt verwezen naar entiteitstypen waarvoor een sleutel is gedefinieerd.
Aanbeveling
U kunt het voorbeeld van dit artikel bekijken op GitHub.
Queries bijhouden
Query's die entiteitstypen retourneren, worden standaard bijgehouden. Een traceringsquery betekent dat wijzigingen in entiteitsexemplaren worden bewaard door SaveChanges. In het volgende voorbeeld wordt de wijziging in de blogsclassificatie gedetecteerd en opgeslagen in de database tijdens SaveChanges:
var blog = await context.Blogs.SingleOrDefaultAsync(b => b.BlogId == 1);
blog.Rating = 5;
await context.SaveChangesAsync();
Wanneer de resultaten worden geretourneerd in een traceringsquery, controleert EF Core of de entiteit zich al in de context bevindt. Als EF Core een bestaande entiteit vindt, wordt hetzelfde exemplaar geretourneerd. Dit kan mogelijk minder geheugen gebruiken en sneller zijn dan een query zonder tracering. EF Core overschrijft de huidige en oorspronkelijke waarden van de eigenschappen van de entiteit niet in de vermelding met de databasewaarden. Als de entiteit niet in de context wordt gevonden, maakt EF Core een nieuw entiteitsexemplaar en koppelt deze aan de context. Queryresultaten bevatten geen entiteit die is toegevoegd aan de context, maar nog niet is opgeslagen in de database.
Geen traceringsquery's
Niet-volgende queries zijn handig wanneer de resultaten worden gebruikt in een situatie waarin alleen gelezen wordt. Ze zijn over het algemeen sneller uit te voeren, omdat het niet nodig is om de gegevens voor het bijhouden van wijzigingen in te stellen. Als de entiteiten die zijn opgehaald uit de database niet hoeven te worden bijgewerkt, moet er een query zonder tracering worden gebruikt. Een afzonderlijke query kan worden ingesteld op geen tracering. Een query zonder tracering geeft ook resultaten op basis van wat zich in de database bevindt, waarbij lokale wijzigingen of toegevoegde entiteiten worden genegeerd.
var blogs = await context.Blogs
.AsNoTracking()
.ToListAsync();
Het standaardgedrag voor bijhouden kan worden gewijzigd op het niveau van het contextexemplaar.
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var blogs = await context.Blogs.ToListAsync();
In de volgende sectie wordt uitgelegd wanneer een query zonder tracering mogelijk minder efficiënt is dan een traceringsquery.
Identiteitsoplossing
Omdat een traceringsquery gebruikmaakt van de wijzigingentracker, voert EF Core identiteitsomzetting uit in een traceringsquery. Bij het materialiseren van een entiteit retourneert EF Core hetzelfde entiteitsexemplaar van de wijzigingentracker als deze al wordt bijgehouden. Als het resultaat meerdere keren dezelfde entiteit bevat, wordt hetzelfde exemplaar geretourneerd voor elk exemplaar. Geen tracingverzoeken
- Gebruik de wijzigingstracker niet en doe geen identiteitsomzetting.
- Retourneert een nieuw exemplaar van de entiteit, zelfs wanneer dezelfde entiteit meerdere keren in het resultaat is opgenomen.
Tracking en no-tracking kunnen worden gecombineerd in dezelfde query. Dat wil zeggen, u kunt een query zonder tracering hebben, die identiteitsresolutie uitvoert in de resultaten. Net als de AsNoTracking querybare operator, hebben we een andere operator AsNoTrackingWithIdentityResolution<TEntity>(IQueryable<TEntity>) toegevoegd. Er is ook een gekoppelde invoer toegevoegd aan de QueryTrackingBehavior enum. Wanneer de query voor het gebruik van identiteitsresolutie is geconfigureerd zonder bijhouden, wordt een zelfstandige wijzigingstracker op de achtergrond gebruikt bij het genereren van queryresultaten, zodat elk exemplaar slechts eenmaal wordt gerealiseerd. Omdat deze wijzigingstracker verschilt van die in de context, worden de resultaten niet bijgehouden door de context. Nadat de query volledig is geïnventariseerd, valt de wijzigingenvolger buiten bereik en worden onnodige gegevens verzameld zoals vereist.
var blogs = await context.Blogs
.AsNoTrackingWithIdentityResolution()
.ToListAsync();
Het standaardtraceringsgedrag configureren
Als u merkt dat u het traceringsgedrag voor veel query's wijzigt, kunt u de standaardinstelling wijzigen:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying.Tracking;Trusted_Connection=True;ConnectRetryCount=0")
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}
Hierdoor worden al uw zoekopdrachten standaard niet gevolgd. U kunt nog steeds toevoegen AsTracking om specifieke query's bij te houden.
Volgen en aangepaste projecties
Zelfs als het resultaattype van de query geen entiteitstype is, houdt EF Core standaard nog steeds entiteitstypen bij die in het resultaat zijn opgenomen. In de volgende query, die een anoniem type retourneert, worden de exemplaren van Blog in de resultaatsset bijgehouden.
var blog = context.Blogs
.Select(
b =>
new { Blog = b, PostCount = b.Posts.Count() });
Als de resultatenset entiteitstypen bevat die afkomstig zijn uit LINQ-samenstelling, worden deze door EF Core bijgehouden.
var blog = context.Blogs
.Select(
b =>
new { Blog = b, Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault() });
Als de resultatenset geen entiteitstypen bevat, wordt er geen tracering uitgevoerd. In de volgende query retourneren we een anoniem type met enkele waarden uit de entiteit (maar geen exemplaren van het werkelijke entiteitstype). Er zijn geen bijgehouden entiteiten die uit de query komen.
var blog = context.Blogs
.Select(
b =>
new { Id = b.BlogId, b.Url });
EF Core ondersteunt het uitvoeren van clientevaluatie in de hoogste-niveau projectie. Als EF Core een entiteitsexemplaar voor clientevaluatie materialiseert, wordt deze bijgehouden. Omdat we hier entiteiten doorgeven blog aan de clientmethode StandardizeURL, worden de blogexemplaren ook door EF Core bijgehouden.
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 houdt de sleutelloze entiteitsexemplaren in het resultaat niet bij. Maar EF Core houdt alle andere exemplaren van entiteitstypen bij met een sleutel volgens de bovenstaande regels.
Vorige versies
Vóór versie 3.0 had EF Core enkele verschillen in de manier waarop het bijhouden werd uitgevoerd. Belangrijke verschillen zijn als volgt:
Zoals uitgelegd op de pagina Client vs Server Evaluation , ondersteunde EF Core-clientevaluatie in een deel van de query vóór versie 3.0. Clientevaluatie veroorzaakte materialisatie van entiteiten, die geen deel uitmaakten van het resultaat. Ef Core heeft daarom het resultaat geanalyseerd om te detecteren wat er moet worden bijgehouden. Dit ontwerp had als volgt bepaalde verschillen:
Clientevaluatie in de projectie, waardoor materialisatie werd veroorzaakt, maar het gerealiseerde entiteitexemplaar niet werd geretourneerd, werd niet bijgehouden. In het volgende voorbeeld zijn de
blogentiteiten niet bijgehouden.var blogs = await context.Blogs .OrderByDescending(blog => blog.Rating) .Select( blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog) }) .ToListAsync();EF Core heeft de objecten die in bepaalde gevallen uit LINQ-samenstelling komen niet bijgehouden. Het volgende voorbeeld heeft
Postniet gevolgd.var blog = context.Blogs .Select( b => new { Blog = b, Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault() });
Wanneer queryresultaten sleutelloze entiteitstypen bevatten, werd de hele query als niet-bijhoudend beschouwd. Dat betekent dat entiteitstypen met sleutels, die zich in het resultaat bevinden, ook niet werden bijgehouden.
EF Core deed vroeger identiteitsherkenning in query's zonder tracering. Er zijn zwakke verwijzingen gebruikt om entiteiten bij te houden die al zijn geretourneerd. Dus als een resultatenset meerdere keren dezelfde entiteit bevat, krijgt u voor elke instantie dezelfde instantie. Als een eerder resultaat met dezelfde identiteit buiten het bereik raakte en door de garbagecollector werd opgehaald, heeft EF Core een nieuw exemplaar geretourneerd.