Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Tijdens het uitvoeren van query's kunt u gegevens uit de database lezen, waarbij u gegevens opslaat door nieuwe entiteiten toe te voegen aan de database, entiteiten te verwijderen of de eigenschappen van bestaande entiteiten op een of andere manier te wijzigen. Entity Framework Core (EF Core) ondersteunt twee fundamentele benaderingen voor het opslaan van gegevens in de database.
Benadering 1: Wijzigingen bijhouden en WijzigingenOpslaan
In veel scenario's moet uw programma een query uitvoeren op bepaalde gegevens uit de database, er een wijziging op uitvoeren en deze wijzigingen weer opslaan; dit wordt ook wel een 'werkeenheid' genoemd. Stel dat u een set blogs hebt en dat u de Url eigenschap van een van deze blogs wilt wijzigen. In EF gebeurt dit meestal als volgt:
using (var context = new BloggingContext())
{
var blog = await context.Blogs.SingleAsync(b => b.Url == "http://example.com");
blog.Url = "http://example.com/blog";
await context.SaveChangesAsync();
}
De bovenstaande code voert de volgende stappen uit:
- Er wordt een reguliere LINQ-query gebruikt om een entiteit uit de database te laden (zie Querygegevens). De query's van EF worden standaard bijgehouden, wat betekent dat EF de geladen entiteiten in de interne wijzigingstracker bijhoudt.
- Het geladen entiteitsexemplaar wordt zoals gebruikelijk gemanipuleerd door een .NET-eigenschap toe te wijzen. EF is niet betrokken bij deze stap.
- Ten slotte wordt DbContext.SaveChanges() aangeroepen. Op dit moment detecteert EF automatisch wijzigingen door de entiteiten te vergelijken met een momentopname vanaf het moment dat ze zijn geladen. Gedetecteerde wijzigingen blijven behouden in de database; wanneer u een relationele database gebruikt, moet dit meestal betrekking hebben op het verzenden van bijvoorbeeld een SQL
UPDATEom de relevante rijen bij te werken.
Houd er rekening mee dat in het bovenstaande een typische updatebewerking voor bestaande gegevens is beschreven, maar vergelijkbare principes gelden voor het toevoegen en verwijderen van entiteiten. U communiceert met de wijzigingentracker van EF door aan te roepen DbSet<TEntity>.Add en Remove, waardoor de wijzigingen worden bijgehouden. EF past vervolgens alle bijgehouden wijzigingen in de database toe wanneer SaveChanges() deze wordt aangeroepen (bijvoorbeeld via SQL INSERT en DELETE wanneer een relationele database wordt gebruikt).
SaveChanges() biedt de volgende voordelen:
- U hoeft geen code te schrijven om bij te houden welke entiteiten en eigenschappen zijn gewijzigd. EF doet dit automatisch voor u en werkt deze eigenschappen alleen bij in de database, waardoor de prestaties worden verbeterd. Stel dat uw geladen entiteiten gebonden zijn aan een UI-onderdeel, zodat gebruikers elke gewenste eigenschap kunnen wijzigen; EF neemt de last weg om uit te zoeken welke entiteiten en eigenschappen daadwerkelijk zijn gewijzigd.
- Het opslaan van wijzigingen in de database kan soms ingewikkeld zijn. Als u bijvoorbeeld een blog en enkele berichten voor dat blog wilt toevoegen, moet u mogelijk de door de database gegenereerde sleutel voor het ingevoegde blog ophalen voordat u de berichten kunt invoegen (omdat ze naar het blog moeten verwijzen). EF doet dit allemaal voor u, wat de complexiteit wegneemt.
- EF kan gelijktijdigheidsproblemen detecteren, bijvoorbeeld wanneer een databaserij is gewijzigd door iemand anders tussen uw query en SaveChanges(). Meer informatie is beschikbaar in gelijktijdigheidsconflicten.
- In databases die dit ondersteunen, SaveChanges() worden automatisch meerdere wijzigingen in een transactie verpakt, zodat uw gegevens consistent blijven als er een fout optreedt. Er zijn meer details beschikbaar in Transacties.
- SaveChanges() batcht ook meerdere wijzigingen in veel gevallen, waardoor het aantal database-rondes aanzienlijk wordt verminderd en de prestaties aanzienlijk worden verbeterd. Meer informatie vindt u in Efficiënt bijwerken.
Zie SaveChanges() voor meer informatie en codevoorbeelden over basisgebruik. Voor meer informatie over het bijhouden van wijzigingen van EF, zie het overzicht van wijzigingen bijhouden.
Aanpak 2: ExecuteUpdate en ExecuteDelete ("bulk update")
Hoewel wijzigingen bijhouden en SaveChanges() een krachtige manier zijn om wijzigingen op te slaan, hebben ze bepaalde nadelen.
SaveChanges() Eerst moet u een query uitvoeren en alle entiteiten bijhouden die u gaat wijzigen of verwijderen. Als u bijvoorbeeld alle blogs met een classificatie onder een bepaalde drempelwaarde wilt verwijderen, moet u een query uitvoeren, een potentieel groot aantal rijen materialiseren en bijhouden en SaveChanges() een DELETE instructie voor elke rij genereren. Relationele databases bieden een veel efficiënter alternatief: één DELETE opdracht kan worden verzonden, waarbij wordt opgegeven welke rijen moeten worden verwijderd via een WHERE component, maar het SaveChanges() model maakt het niet mogelijk om die te genereren.
Ter ondersteuning van dit scenario voor bulkupdates kunt u het volgende gebruiken ExecuteDelete :
context.Blogs.Where(b => b.Rating < 3).ExecuteDelete();
Hiermee kunt u een SQL-instructie DELETE uitdrukken via reguliere LINQ-operators, vergelijkbaar met een reguliere LINQ-query, waardoor de volgende SQL wordt uitgevoerd op de database:
DELETE FROM [b]
FROM [Blogs] AS [b]
WHERE [b].[Rating] < 3
Dit wordt zeer efficiënt uitgevoerd in de database, zonder gegevens uit de database te laden of de wijzigingentracker van EF te betrekken. Op dezelfde manier kunt u met ExecuteUpdate een SQL-instructie UPDATE uitdrukken.
Zelfs als u niet bulksgewijs entiteiten wijzigt, weet u mogelijk precies welke eigenschappen van welke entiteit u wilt wijzigen. Het gebruik van de API voor het bijhouden van wijzigingen kan te complex zijn: u moet een entiteitexemplaar maken, het bijhouden via Attach, uw wijzigingen aanbrengen en ten slotte SaveChanges() aanroepen. Voor dergelijke scenario's ExecuteUpdateExecuteDelete kan het een aanzienlijk eenvoudigere manier zijn om dezelfde bewerking uit te drukken.
Ten slotte leggen zowel wijzigingen bijhouden als SaveChanges() zichzelf een bepaalde runtime-overhead op. Als u een toepassing met hoge prestaties schrijft, kunt u zowel ExecuteUpdate als ExecuteDelete vermijden en efficiënt de gewenste instructie genereren.
Houd er echter rekening mee dat ExecuteUpdate en ExecuteDelete ook bepaalde beperkingen hebben:
- Deze methoden worden onmiddellijk uitgevoerd en kunnen momenteel niet worden gebatcheerd met andere bewerkingen. Aan de andere kant kan SaveChanges() meerdere bewerkingen in batches verwerken.
- Aangezien het bijhouden van wijzigingen niet betrokken is, is het uw verantwoordelijkheid om precies te weten welke entiteiten en eigenschappen moeten worden gewijzigd. Dit kan betekenen dat het bijhouden van wat er op laag niveau moet worden gewijzigd en wat niet, meer handmatig coderen vereist.
- Aangezien er geen wijzigingen worden bijgehouden, wordt met deze methoden gelijktijdigheidsbeheer niet automatisch toegepast wanneer wijzigingen worden bewaard. U kunt echter nog steeds expliciet een
Wherecomponent toevoegen om gelijktijdigheidsbeheer zelf te implementeren. - Alleen het bijwerken en verwijderen wordt momenteel ondersteund; invoeging moet worden uitgevoerd via DbSet<TEntity>.Add en SaveChanges().
Voor meer informatie en codevoorbeelden, zie ExecuteUpdate en ExecuteDelete.
Samenvatting
Hieronder volgen enkele richtlijnen voor het gebruik van welke benadering. Houd er rekening mee dat dit geen absolute regels zijn, maar een handige vuistregel bieden:
- Als u niet van tevoren weet welke wijzigingen zullen plaatsvinden, gebruikt
SaveChangesu ; deze detecteert automatisch welke wijzigingen moeten worden toegepast. Voorbeeldscenario's:- "Ik wil een blog uit de database laden en een formulier weergeven waarmee de gebruiker het kan wijzigen"
- Als u een grafiek met objecten (d.w.w.v. meerdere onderling verbonden objecten) moet bewerken, gebruikt
SaveChangesu ; het zal de juiste volgorde van de wijzigingen bepalen en hoe u alles aan elkaar kunt koppelen.- "Ik wil een blog bijwerken, enkele van de berichten wijzigen en anderen verwijderen"
- Als u een potentieel groot aantal entiteiten wilt wijzigen op basis van een bepaald criterium, gebruikt u
ExecuteUpdateenExecuteDelete. Voorbeeldscenario's:- "Ik wil alle werknemers een verhoging geven"
- "Ik wil alle blogs verwijderen waarvan de naam begint met X"
- Als u al precies weet welke entiteiten u wilt wijzigen en hoe u ze wilt wijzigen, gebruikt
ExecuteUpdateu enExecuteDelete. Voorbeeldscenario's:- "Ik wil de blog verwijderen waarvan de naam 'Foo' is"
- Ik wil de naam van blog met id 5 wijzigen naar 'Bar'