Arbeta med entitetstillstånd

Det här avsnittet beskriver hur du lägger till och kopplar entiteter till en kontext och hur Entity Framework bearbetar dessa under SaveChanges. Entity Framework tar hand om att spåra tillståndet för entiteter när de är anslutna till en kontext, men i frånkopplade scenarier eller N-nivåscenarier kan du låta EF veta vilket tillstånd dina entiteter ska vara i. De tekniker som visas i det här avsnittet gäller lika för modeller som skapats med Code First och EF Designer.

Entitetstillstånd och SaveChanges

En entitet kan vara i ett av fem tillstånd enligt definitionen i EntityState-uppräkningen. Dessa tillstånd är:

  • Tillagd: entiteten spåras av kontexten men finns ännu inte i databasen
  • Oförändrad: entiteten spåras av kontexten och finns i databasen och dess egenskapsvärden har inte ändrats från värdena i databasen
  • Ändrad: entiteten spåras av kontexten och finns i databasen, och vissa eller alla dess egenskapsvärden har ändrats
  • Borttagen: entiteten spåras av kontexten och finns i databasen, men har markerats för borttagning från databasen nästa gång SaveChanges anropas
  • Frånkopplad: entiteten spåras inte av kontexten

SaveChanges gör olika saker för entiteter i olika tillstånd:

  • Oförändrade entiteter berörs inte av SaveChanges. Uppdateringar skickas inte till databasen för entiteter i tillståndet Oförändrad.
  • Entiteter som lagts till infogas i databasen och blir sedan oförändrade när SaveChanges returnerar.
  • Ändrade entiteter uppdateras i databasen och blir sedan Oförändrade när SaveChanges returneras.
  • Borttagna entiteter tas bort från databasen och kopplas sedan från sammanhanget.

I följande exempel visas hur tillståndet för en entitet eller en entitetsdiagram kan ändras.

Lägga till en ny entitet i kontexten

En ny entitet kan läggas till i kontexten genom att anropa metoden Lägg till på DbSet. Detta placerar entiteten i tillståndet Lägg till, vilket innebär att den infogas i databasen nästa gång som SaveChanges anropas. Som exempel:

using (var context = new BloggingContext())
{
    var blog = new Blog { Name = "ADO.NET Blog" };
    context.Blogs.Add(blog);
    context.SaveChanges();
}

Ett annat sätt att lägga till en ny entitet i kontexten är att ändra dess tillstånd till Tillagda. Som exempel:

using (var context = new BloggingContext())
{
    var blog = new Blog { Name = "ADO.NET Blog" };
    context.Entry(blog).State = EntityState.Added;
    context.SaveChanges();
}

Slutligen kan du lägga till en ny entitet i kontexten genom att koppla den till en annan entitet som redan spåras. Det kan vara genom att lägga till den nya entiteten i samlingsnavigeringsegenskapen för en annan entitet eller genom att ange en referensnavigeringsegenskap för en annan entitet så att den pekar på den nya entiteten. Som exempel:

using (var context = new BloggingContext())
{
    // Add a new User by setting a reference from a tracked Blog
    var blog = context.Blogs.Find(1);
    blog.Owner = new User { UserName = "johndoe1987" };

    // Add a new Post by adding to the collection of a tracked Blog
    blog.Posts.Add(new Post { Name = "How to Add Entities" });

    context.SaveChanges();
}

Observera att för alla dessa exempel om entiteten som läggs till har referenser till andra entiteter som ännu inte spåras läggs även dessa nya entiteter till i kontexten och infogas i databasen nästa gång som SaveChanges anropas.

Koppla en befintlig entitet till kontexten

Om du har en entitet som du vet redan finns i databasen men som för närvarande inte spåras av kontexten kan du be kontexten att spåra entiteten med hjälp av metoden Bifoga på DbSet. Entiteten kommer att ha tillståndet Oförändrad i kontexten. Som exempel:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Blogs.Attach(existingBlog);

    // Do some more work...  

    context.SaveChanges();
}

Observera att inga ändringar görs i databasen om SaveChanges anropas utan någon annan manipulering av den anslutna entiteten. Det beror på att entiteten är i tillståndet Oförändrad.

Ett annat sätt att koppla en befintlig entitet till kontexten är att ändra dess tillstånd till Oförändrad. Som exempel:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Unchanged;

    // Do some more work...  

    context.SaveChanges();
}

Observera att för båda dessa exempel om entiteten som kopplas har referenser till andra entiteter som ännu inte spåras, kommer dessa nya entiteter också att kopplas till kontexten i tillståndet Oförändrat.

Koppla en befintlig men modifierad entitet till kontexten

Om du har en entitet som du vet redan finns i databasen men till vilken ändringar kan ha gjorts kan du be kontexten att koppla entiteten och ange dess tillstånd till Ändrad. Som exempel:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Modified;

    // Do some more work...  

    context.SaveChanges();
}

När du ändrar tillståndet till Ändrad markeras alla egenskaper för entiteten som ändrade och alla egenskapsvärden skickas till databasen när SaveChanges anropas.

Observera att om entiteten som kopplas har referenser till andra entiteter som ännu inte spåras, kommer dessa nya entiteter att kopplas till kontexten i tillståndet Oförändrad– de ändras inte automatiskt. Om du har flera entiteter som måste markeras som Ändrade bör du ange tillståndet för var och en av dessa entiteter individuellt.

Ändra tillståndet för en spårad entitet

Du kan ändra tillståndet för en entitet som redan spåras genom att ange egenskapen State på dess post. Som exempel:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Blogs.Attach(existingBlog);
    context.Entry(existingBlog).State = EntityState.Unchanged;

    // Do some more work...  

    context.SaveChanges();
}

Observera att anrop till Lägg till eller Bifoga för en entitet som redan spåras också kan användas för att ändra entitetstillståndet. Om du till exempel anropar Bifoga för en entitet som för närvarande är i tillståndet Lägg till ändras dess tillstånd till Oförändrat.

Infoga eller uppdatera mönster

Ett vanligt mönster för vissa program är att antingen Lägga till en entitet som ny (vilket resulterar i en databasinfogning) eller Bifoga en entitet som befintlig och markera den som ändrad (vilket resulterar i en databasuppdatering) beroende på värdet för den primära nyckeln. När du till exempel använder primärnycklar för databasgenererade heltal är det vanligt att behandla en entitet med en nollnyckel som ny och en entitet med en icke-nollnyckel som befintlig. Det här mönstret kan uppnås genom att ange entitetstillståndet baserat på en kontroll av primärnyckelvärdet. Som exempel:

public void InsertOrUpdate(Blog blog)
{
    using (var context = new BloggingContext())
    {
        context.Entry(blog).State = blog.BlogId == 0 ?
                                   EntityState.Added :
                                   EntityState.Modified;

        context.SaveChanges();
    }
}

Observera att när du ändrar tillståndet till Ändrad markeras alla egenskaper för entiteten som ändrade och alla egenskapsvärden skickas till databasen när SaveChanges anropas.