Práce se stavy entit

V tomto tématu se dozvíte, jak přidat a připojit entity k kontextu a jak entity Framework zpracovává tyto entity během saveChanges. Entity Framework se stará o sledování stavu entit, když jsou připojené k kontextu, ale v odpojených nebo N-vrstvých scénářích můžete systému EF dát vědět, v jakém stavu se mají entity nacházet. Techniky uvedené v tomto tématu jsou rovnocenné pro modely vytvořené pomocí Code First a EF Designeru.

Stavy entit a SaveChanges

Entita může být v jednom z pěti stavů definovaných výčtem EntityState. Tyto stavy:

  • Přidáno: Entita je sledována kontextem, ale zatím v databázi neexistuje.
  • Beze změny: Entita je sledována kontextem a existuje v databázi a její hodnoty vlastností se nezměnily z hodnot v databázi.
  • Změněno: Entita je sledována kontextem a existuje v databázi a některé nebo všechny jeho hodnoty vlastností byly změněny.
  • Odstraněno: Entita je sledována kontextem a existuje v databázi, ale byla označena k odstranění z databáze při příštím zavolání SaveChanges.
  • Odpojeno: entita není sledována kontextem

Funkce SaveChanges dělá různé věci pro entity v různých stavech:

  • Funkce SaveChanges neobsahuje nezměněné entity. Aktualizace se do databáze neodesílají entity v nezměněném stavu.
  • Přidané entity se vloží do databáze a po vrácení funkce SaveChanges se změní na beze změny.
  • Změněné entity se aktualizují v databázi a po vrácení funkce SaveChanges se změní na beze změny.
  • Odstraněné entity se z databáze odstraní a pak se odpojily od kontextu.

Následující příklady ukazují způsoby, jak se dá změnit stav entity nebo grafu entity.

Přidání nové entity do kontextu

Do kontextu lze přidat novou entitu voláním metody Add v DbSet. Tím se entita vloží do stavu Přidání, což znamená, že se při příštím zavolání SaveChanges vloží do databáze. Příklad:

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

Dalším způsobem, jak do kontextu přidat novou entitu, je změnit její stav na Přidaný. Příklad:

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

Nakonec můžete do kontextu přidat novou entitu tak, že ji připojíte k jiné entitě, kterou už sledujete. To může být přidáním nové entity do navigační vlastnosti kolekce jiné entity nebo nastavením referenční navigační vlastnosti jiné entity tak, aby odkaz na novou entitu. Příklad:

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

Všimněte si, že pokud přidaná entita obsahuje odkazy na jiné entity, které ještě nejsou sledovány, budou tyto nové entity přidány také do kontextu a budou vloženy do databáze při příštím zavolání SaveChanges.

Připojení existující entity k kontextu

Pokud máte entitu, o které víte, že již v databázi existuje, ale která není aktuálně sledována kontextem, můžete kontextu sdělit, aby sledoval entitu pomocí metody Attach v DbSet. Entita bude v kontextu beze změny. Příklad:

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

Všimněte si, že v databázi nebudou provedeny žádné změny, pokud je volána funkce SaveChanges, aniž by došlo k žádné jiné manipulaci s připojenou entitou. Důvodem je to, že entita je ve stavu Beze změny.

Dalším způsobem, jak připojit existující entitu k kontextu, je změnit její stav na Beze změny. Příklad:

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

Všimněte si, že pro oba tyto příklady platí, že pokud připojená entita obsahuje odkazy na jiné entity, které ještě nejsou sledovány, budou tyto nové entity také připojeny k kontextu v nezměněném stavu.

Připojení existující, ale upravené entity k kontextu

Pokud máte entitu, o které víte, že již v databázi existuje, ale ke kterým změnám mohlo dojít, můžete kontextu sdělit, aby připojil entitu a nastavil její stav na Změněno. Příklad:

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

Když změníte stav na Změněno všechny vlastnosti entity budou označeny jako změněné a všechny hodnoty vlastností budou odeslány do databáze při zavolání SaveChanges.

Všimněte si, že pokud připojená entita obsahuje odkazy na jiné entity, které ještě nejsou sledovány, budou tyto nové entity připojeny k kontextu v nezměněném stavu – nebudou automaticky změněny. Pokud máte více entit, které je potřeba označit Jako změněné, měli byste pro každou z těchto entit nastavit stav jednotlivě.

Změna stavu sledované entity

Stav entity, která je již sledována, můžete změnit nastavením state vlastnost u jeho položky. Příklad:

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

Všimněte si, že volání Přidat nebo Připojit pro entitu, která je již sledována, lze také použít ke změně stavu entity. Například volání Připojit pro entitu, která je aktuálně v přidaném stavu, změní stav na Beze změny.

Vzor vložení nebo aktualizace

Běžným vzorem některých aplikací je buď přidat entitu jako novou (což vede k vložení databáze), nebo připojit entitu jako existující a označit ji jako upravenou (výsledkem je aktualizace databáze) v závislosti na hodnotě primárního klíče. Například při použití primárních klíčů vygenerovaných celočíselnou databází je běžné považovat entitu s nulovým klíčem jako nový a entitu s nenulovým klíčem jako existujícím. Tento model lze dosáhnout nastavením stavu entity na základě kontroly hodnoty primárního klíče. Příklad:

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

        context.SaveChanges();
    }
}

Všimněte si, že když změníte stav na Změněno všechny vlastnosti entity budou označeny jako změněné a všechny hodnoty vlastností budou odeslány do databáze při zavolání SaveChanges.