Dela via


Spara data

När du frågar kan du läsa data från databasen, men att spara data innebär att lägga till nya entiteter i databasen, ta bort entiteter eller ändra egenskaperna för befintliga entiteter på något sätt. Entity Framework Core (EF Core) stöder två grundläggande metoder för att spara data i databasen.

Metod 1: ändringsspårning och SaveChanges

I många scenarier måste programmet köra frågor mot vissa data från databasen, utföra vissa ändringar på den och spara ändringarna igen. Detta kallas ibland för en "arbetsenhet". Anta till exempel att du har en uppsättning bloggar och vill ändra egenskapen för Url en av dem. I EF görs detta vanligtvis på följande sätt:

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();
}

Koden ovan utför följande steg:

  1. Den använder en vanlig LINQ-fråga för att läsa in en entitet från databasen (se Frågedata). EF:s frågor är som standard spårade, vilket innebär att EF följer de inlästa entiteterna i sin interna ändringslogg.
  2. Den inlästa entitetsinstansen manipuleras som vanligt genom att tilldela en .NET-egenskap. EF ingår inte i det här steget.
  3. Slutligen anropas DbContext.SaveChanges(). I det här läget identifierar EF automatiskt alla ändringar genom att jämföra entiteterna med en ögonblicksbild från det ögonblick då de lästes in. Alla identifierade ändringar sparas i databasen. När du använder en relationsdatabas innebär detta vanligtvis att skicka t.ex. en SQL UPDATE för att uppdatera relevanta rader.

Observera att ovanstående beskrev en typisk uppdateringsåtgärd för befintliga data, men liknande principer gäller för att lägga till och ta bort entiteter. Du interagerar med EF:s ändringsspårare genom att anropa DbSet<TEntity>.Add och Remove, vilket gör att ändringarna spåras. EF tillämpar sedan alla spårade ändringar på databasen när SaveChanges() anropas (t.ex. via SQL INSERT och DELETE när du använder en relationsdatabas).

SaveChanges() erbjuder följande fördelar:

  • Du behöver inte skriva kod för att spåra vilka entiteter och egenskaper som ändrats – EF gör detta automatiskt åt dig och uppdaterar bara dessa egenskaper i databasen, vilket förbättrar prestandan. Tänk dig om dina inlästa entiteter är bundna till en UI-komponent, så att användarna kan ändra vilken egenskap de vill. EF tar bort bördan att ta reda på vilka entiteter och egenskaper som faktiskt ändrades.
  • Det kan ibland vara komplicerat att spara ändringar i databasen! Om du till exempel vill lägga till en blogg och några inlägg för den bloggen kan du behöva hämta den databasgenererade nyckeln för den infogade bloggen innan du kan infoga inläggen (eftersom de måste referera till bloggen). EF gör allt detta åt dig och tar bort komplexiteten.
  • EF kan identifiera samtidighetsproblem, till exempel när en databasrad har ändrats av någon annan mellan din fråga och SaveChanges(). Mer information finns i samtidighetskonflikter.
  • På databaser som stöder den omsluter SaveChanges() automatiskt flera ändringar i en transaktion, vilket säkerställer att dina data förblir konsekventa om ett fel inträffar. Mer information finns i Transaktioner.
  • SaveChanges() batchar också ihop flera ändringar i många fall, vilket avsevärt minskar antalet databasrundor och avsevärt förbättrar prestandan. Mer information finns i Effektiv uppdatering.

Mer information och kodexempel om grundläggande SaveChanges() användning finns i Grundläggande SaveChanges. Mer information om EF:s ändringsspårning finns i översikten över ändringsspårning.

Metod 2: ExecuteUpdate och ExecuteDelete ("massuppdatering")

Även om ändringsspårning och SaveChanges() är ett kraftfullt sätt att spara ändringar, har de vissa nackdelar.

Först kräver SaveChanges() att du frågar om och spårar alla entiteter som du kommer att ändra eller ta bort. Om du till exempel behöver ta bort alla bloggar med ett omdöme under ett visst tröskelvärde måste du köra en fråga, ta fram och spåra ett potentiellt enormt antal rader och ha SaveChanges() generera ett DELETE-påstående för var och en av dem. Relationsdatabaser är ett mycket effektivare alternativ: ett enda DELETE kommando kan skickas och ange vilka rader som ska tas bort via en WHERE sats, men SaveChanges() modellen tillåter inte att det genereras.

Om du vill stödja det här scenariot med massuppdatering kan du använda ExecuteDelete följande:

context.Blogs.Where(b => b.Rating < 3).ExecuteDelete();

På så sätt kan du uttrycka en SQL-instruktion DELETE via vanliga LINQ-operatorer , ungefär som en vanlig LINQ-fråga, vilket gör att följande SQL körs mot databasen:

DELETE FROM [b]
FROM [Blogs] AS [b]
WHERE [b].[Rating] < 3

Detta körs mycket effektivt i databasen, utan att läsa in några data från databasen eller med EF:s ändringsspårare. ExecuteUpdate På samma sätt kan du uttrycka en SQL-instruktionUPDATE.

Även om du inte ändrar entiteter i grupp kanske du vet exakt vilka egenskaper för vilken entitet du vill ändra. Att använda API:et för ändringsspårning för att utföra ändringen kan vara alltför komplext, kräver att du skapar en entitetsinstans, spårar den via Attach, gör dina ändringar och slutligen anropar SaveChanges(). För sådana scenarier kan ExecuteUpdate och ExecuteDelete vara ett betydligt enklare sätt att uttrycka samma åtgärd.

Slutligen medför både ändringsspårning och SaveChanges() själv en viss körningsoverhead. Om du skriver en högpresterande applikation, tillåter ExecuteUpdate och ExecuteDelete dig att undvika båda dessa komponenter och effektivt generera den instruktion du önskar.

Observera dock att ExecuteUpdate och ExecuteDelete även har vissa begränsningar:

  • Dessa metoder körs omedelbart och kan för närvarande inte batchas med andra åtgärder. Å andra sidan kan SaveChanges() gruppera flera åtgärder tillsammans.
  • Eftersom ändringsspårning inte ingår är det ditt ansvar att veta exakt vilka entiteter och egenskaper som måste ändras. Det kan innebära mer manuell kodspårning på låg nivå vad som behöver ändras och vad som inte gör det.
  • Eftersom ändringsspårning inte ingår tillämpas inte samtidighetskontroll automatiskt när ändringar sparas. Du kan dock fortfarande uttryckligen lägga till en Where sats för att implementera samtidighetskontroll själv.
  • För närvarande stöds endast uppdatering och borttagning. infogning måste göras via DbSet<TEntity>.Add och SaveChanges().

Mer information och kodexempel finns i ExecuteUpdate och ExecuteDelete.

Sammanfattning

Nedan följer några riktlinjer för när du ska använda vilken metod. Observera att dessa inte är absoluta regler, utan ger användbara tumregler:

  • Om du inte vet i förväg vilka ändringar som ska göras använder du SaveChanges. Det identifierar automatiskt vilka ändringar som måste tillämpas. Exempelscenarier:
    • "Jag vill läsa in en blogg från databasen och visa ett formulär som gör att användaren kan ändra den"
  • Om du behöver ändra ett diagram över objekt (dvs. flera sammankopplade objekt) använder SaveChangesdu . Det tar reda på rätt ordning på ändringarna och hur du länkar ihop allt.
    • "Jag vill uppdatera en blogg, ändra några av dess inlägg och ta bort andra"
  • Om du vill ändra ett potentiellt stort antal entiteter baserat på något kriterium använder du ExecuteUpdate och ExecuteDelete. Exempelscenarier:
    • "Jag vill ge alla anställda en höjning"
    • "Jag vill ta bort alla bloggar vars namn börjar med X"
  • Om du redan vet exakt vilka entiteter du vill ändra och hur du vill ändra dem, använder du ExecuteUpdate och ExecuteDelete. Exempelscenarier:
    • "Jag vill ta bort bloggen vars namn är 'Foo'"
    • "Jag vill ändra namnet på bloggen med ID 5 till 'Bar'"