Přístup ke sledovaným entitě

Existují čtyři hlavní rozhraní API pro přístup k entitám sledovaným pomocí DbContext:

Každý z nich je podrobněji popsán v následujících částech.

Tip

Tento dokument předpokládá, že stavy entit a základy sledování změn EF Core jsou srozumitelné. Další informace o těchto tématech najdete v tématu Sledování změn v EF Core .

Tip

Celý kód v tomto dokumentu můžete spustit a ladit tak, že si stáhnete ukázkový kód z GitHubu.

Použití instancí DbContext.Entry a EntityEntry

U každé sledované entity sleduje Entity Framework Core (EF Core):

  • Celkový stav entity. Toto je jedna z hodnot , , nebo Deleted; viz Change Tracking v EF Core další Addedinformace. ModifiedUnchanged
  • Vztahy mezi sledovanými entitami. Například blog, do kterého příspěvek patří.
  • "Aktuální hodnoty" vlastností.
  • "Původní hodnoty" vlastností, pokud jsou tyto informace k dispozici. Původní hodnoty jsou hodnoty vlastností, které existovaly, když byla entita dotazována z databáze.
  • Které hodnoty vlastností byly změněny od doby, kdy byly dotazovány.
  • Další informace o hodnotách vlastností, například zda je hodnota dočasná.

Předání instance entity, aby DbContext.Entry výsledkem bylo EntityEntry<TEntity> poskytnutí přístupu k tomuto informacím pro danou entitu. Příklad:

using var context = new BlogsContext();

var blog = context.Blogs.Single(e => e.Id == 1);
var entityEntry = context.Entry(blog);

Následující části ukazují, jak pomocí EntityEntry přistupovat ke stavu entity a manipulovat s nimi a také se stavem vlastností a navigace entity.

Práce s entitou

Nejběžnějším použitím EntityEntry<TEntity> je přístup k aktuálnímu EntityState stavu entity. Příklad:

var currentState = context.Entry(blog).State;
if (currentState == EntityState.Unchanged)
{
    context.Entry(blog).State = EntityState.Modified;
}

Metodu Entry lze použít také u entit, které ještě nejsou sledovány. Tím se nezačne sledovat entitu; stav entity je stále Detached. Vrácená entita EntityEntry se pak dá použít ke změně stavu entity, v jakém okamžiku se entita bude sledovat v daném stavu. Například následující kód začne sledovat instanci blogu jako Added:

var newBlog = new Blog();
Debug.Assert(context.Entry(newBlog).State == EntityState.Detached);

context.Entry(newBlog).State = EntityState.Added;
Debug.Assert(context.Entry(newBlog).State == EntityState.Added);

Tip

Na rozdíl od EF6 nastavení stavu jednotlivé entity nezpůsobí sledování všech propojených entit. Tím se nastaví stav tímto způsobem jako operace nižší úrovně než volání Add, Attachnebo Update, které pracují s celým grafem entit.

Následující tabulka shrnuje způsoby použití EntityEntry k práci s celou entitou:

EntityEntry – člen Popis
EntityEntry.State Získá a nastaví EntityState entitu.
EntityEntry.Entity Získá instanci entity.
EntityEntry.Context Tato entita DbContext sleduje.
EntityEntry.Metadata IEntityType metadata pro typ entity.
EntityEntry.IsKeySet Určuje, jestli má entita nastavenou hodnotu klíče.
EntityEntry.Reload() Přepíše hodnoty vlastností hodnotami načtenými z databáze.
EntityEntry.DetectChanges() Vynutí detekci změn pouze pro tuto entitu; viz Detekce změn a oznámení.

Práce s jednou vlastností

Několik přetížení EntityEntry<TEntity>.Property povolení přístupu k informacím o individuální vlastnosti entity. Například použití rozhraní API se silným typem, fluent-like:

PropertyEntry<Blog, string> propertyEntry = context.Entry(blog).Property(e => e.Name);

Název vlastnosti lze místo toho předat jako řetězec. Příklad:

PropertyEntry<Blog, string> propertyEntry = context.Entry(blog).Property<string>("Name");

PropertyEntry<TEntity,TProperty> Vrácená vlastnost se pak dá použít pro přístup k informacím o vlastnosti. Dá se například použít k získání a nastavení aktuální hodnoty vlastnosti u této entity:

string currentValue = context.Entry(blog).Property(e => e.Name).CurrentValue;
context.Entry(blog).Property(e => e.Name).CurrentValue = "1unicorn2";

Obě metody vlastnosti použité výše vrátí obecnou instanci silného typu PropertyEntry<TEntity,TProperty> . Použití tohoto obecného typu je upřednostňované, protože umožňuje přístup k hodnotám vlastností bez krabicových typů hodnot. Pokud však typ entity nebo vlastnosti není v době kompilace znám, lze místo toho získat jiný než obecný PropertyEntry :

PropertyEntry propertyEntry = context.Entry(blog).Property("Name");

To umožňuje přístup k informacím o vlastnosti pro libovolnou vlastnost bez ohledu na její typ, a to na úkor krabicových hodnotových typů. Příklad:

object blog = context.Blogs.Single(e => e.Id == 1);

object currentValue = context.Entry(blog).Property("Name").CurrentValue;
context.Entry(blog).Property("Name").CurrentValue = "1unicorn2";

Následující tabulka shrnuje informace o vlastnosti vystavené propertyEntry:

PropertyEntry – člen Popis
PropertyEntry<TEntity,TProperty>.CurrentValue Získá a nastaví aktuální hodnotu vlastnosti.
PropertyEntry<TEntity,TProperty>.OriginalValue Získá a nastaví původní hodnotu vlastnosti, pokud je k dispozici.
PropertyEntry<TEntity,TProperty>.EntityEntry Zpětný odkaz na entitu EntityEntry<TEntity> .
PropertyEntry.Metadata IProperty metadata vlastnosti.
PropertyEntry.IsModified Určuje, zda je tato vlastnost označena jako změněna, a umožňuje změnit tento stav.
PropertyEntry.IsTemporary Určuje, zda je tato vlastnost označena jako dočasná, a umožňuje změnit tento stav.

Poznámky:

  • Původní hodnota vlastnosti je hodnota, kterou vlastnost měla při dotazování entity z databáze. Původní hodnoty však nejsou k dispozici, pokud byla entita odpojena a explicitně připojena k jiné dbContext, například s Attach nebo Update. V tomto případě bude vrácená původní hodnota stejná jako aktuální hodnota.
  • SaveChanges aktualizuje pouze vlastnosti označené jako změněné. Nastavte IsModified hodnotu true, aby EF Core aktualizovala danou hodnotu vlastnosti, nebo ji nastavte na false, aby ef Core nemohla aktualizovat hodnotu vlastnosti.
  • Dočasné hodnoty se obvykle generují generátory hodnot EF Core. Nastavení aktuální hodnoty vlastnosti nahradí dočasnou hodnotu danou hodnotou a označí vlastnost jako ne dočasnou. Hodnota IsTemporary true se nastaví tak, aby byla hodnota dočasná i po explicitní sadě.

Práce s jednou navigací

Několik přetížení EntityEntry<TEntity>.Reference, EntityEntry<TEntity>.Collectiona EntityEntry.Navigation povolit přístup k informacím o individuální navigaci.

Referenční navigace k jedné související entitě jsou přístupné prostřednictvím Reference metod. Odkazy na navigace ukazují na stranu "jedna" relací 1:N a obě strany relací 1:1. Příklad:

ReferenceEntry<Post, Blog> referenceEntry1 = context.Entry(post).Reference(e => e.Blog);
ReferenceEntry<Post, Blog> referenceEntry2 = context.Entry(post).Reference<Blog>("Blog");
ReferenceEntry referenceEntry3 = context.Entry(post).Reference("Blog");

Navigace můžou být také kolekce souvisejících entit, pokud se používají pro strany "N" relací 1:N a M:N. Metody Collection se používají pro přístup k navigaci v kolekci. Příklad:

CollectionEntry<Blog, Post> collectionEntry1 = context.Entry(blog).Collection(e => e.Posts);
CollectionEntry<Blog, Post> collectionEntry2 = context.Entry(blog).Collection<Post>("Posts");
CollectionEntry collectionEntry3 = context.Entry(blog).Collection("Posts");

Některé operace jsou společné pro všechny navigace. K těmto odkazům i k navigaci kolekcí je možné získat přístup pomocí EntityEntry.Navigation metody. Mějte na paměti, že při společném přístupu ke všem navigačním panelům je k dispozici pouze ne generický přístup. Příklad:

NavigationEntry navigationEntry = context.Entry(blog).Navigation("Posts");

Následující tabulka shrnuje způsoby použití ReferenceEntry<TEntity,TProperty>, CollectionEntry<TEntity,TRelatedEntity>a NavigationEntry:

Člen NavigationEntry Popis
MemberEntry.CurrentValue Získá a nastaví aktuální hodnotu navigace. Toto je celá kolekce pro navigaci v kolekcích.
NavigationEntry.Metadata INavigationBase metadata pro navigaci.
NavigationEntry.IsLoaded Získá nebo nastaví hodnotu určující, zda související entita nebo kolekce byla plně načtena z databáze.
NavigationEntry.Load() Načte související entitu nebo kolekci z databáze; Viz Explicitní načítání souvisejících dat.
NavigationEntry.Query() Dotaz EF Core by použil k načtení této navigace jako IQueryable objektu, který se dá dále skládat. Viz Explicitní načítání souvisejících dat.

Práce se všemi vlastnostmi entity

EntityEntry.Properties vrátí hodnotu IEnumerable<T> PropertyEntry pro každou vlastnost entity. Dá se použít k provedení akce pro každou vlastnost entity. Pokud například chcete nastavit libovolnou vlastnost DateTime na DateTime.Now:

foreach (var propertyEntry in context.Entry(blog).Properties)
{
    if (propertyEntry.Metadata.ClrType == typeof(DateTime))
    {
        propertyEntry.CurrentValue = DateTime.Now;
    }
}

Kromě toho EntityEntry obsahuje několik metod pro získání a nastavení všech hodnot vlastností najednou. Tyto metody používají PropertyValues třídu, která představuje kolekci vlastností a jejich hodnot. VlastnostiValue lze získat pro aktuální nebo původní hodnoty nebo pro hodnoty, které jsou aktuálně uloženy v databázi. Příklad:

var currentValues = context.Entry(blog).CurrentValues;
var originalValues = context.Entry(blog).OriginalValues;
var databaseValues = context.Entry(blog).GetDatabaseValues();

Tyto Objekty PropertyValues nejsou samy o sobě velmi užitečné. Lze je ale zkombinovat a provádět běžné operace potřebné při manipulaci s entitami. To je užitečné při práci s objekty přenosu dat a při řešení optimistických konfliktů souběžnosti. V následujících částech najdete několik příkladů.

Nastavení aktuálních nebo původních hodnot z entity nebo DTO

Aktuální nebo původní hodnoty entity lze aktualizovat zkopírováním hodnot z jiného objektu. Představte si BlogDto například objekt přenosu dat (DTO) se stejnými vlastnostmi jako typ entity:

public class BlogDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

To lze použít k nastavení aktuálních hodnot sledované entity pomocí PropertyValues.SetValues:

var blogDto = new BlogDto { Id = 1, Name = "1unicorn2" };

context.Entry(blog).CurrentValues.SetValues(blogDto);

Tato technika se někdy používá při aktualizaci entity s hodnotami získanými z volání služby nebo klienta v n-vrstvé aplikaci. Všimněte si, že použitý objekt nemusí být stejného typu jako entita, pokud má vlastnosti, jejichž názvy odpovídají názvům entity. V předchozím příkladu se instance DTO BlogDto používá k nastavení aktuálních hodnot sledované Blog entity.

Všimněte si, že vlastnosti se označí jako změněné, pouze pokud se sada hodnot liší od aktuální hodnoty.

Nastavení aktuálních nebo původních hodnot ze slovníku

Předchozí příklad nastavil hodnoty z entity nebo instance DTO. Stejné chování je k dispozici, pokud jsou hodnoty vlastností uloženy jako páry název/hodnota ve slovníku. Příklad:

var blogDictionary = new Dictionary<string, object> { ["Id"] = 1, ["Name"] = "1unicorn2" };

context.Entry(blog).CurrentValues.SetValues(blogDictionary);

Nastavení aktuálních nebo původních hodnot z databáze

Aktuální nebo původní hodnoty entity lze aktualizovat nejnovějšími hodnotami z databáze voláním GetDatabaseValues() nebo GetDatabaseValuesAsync použitím vráceného objektu k nastavení aktuálních nebo původních hodnot nebo obojího. Příklad:

var databaseValues = context.Entry(blog).GetDatabaseValues();
context.Entry(blog).CurrentValues.SetValues(databaseValues);
context.Entry(blog).OriginalValues.SetValues(databaseValues);

Vytvoření klonovaného objektu obsahujícího aktuální, původní nebo databázové hodnoty

PropertyValues objekt vrácený z CurrentValues, OriginalValues nebo GetDatabaseValues lze použít k vytvoření klon entity pomocí PropertyValues.ToObject(). Příklad:

var clonedBlog = context.Entry(blog).GetDatabaseValues().ToObject();

Všimněte si, že ToObject vrátí novou instanci, která není sledována DbContext. Vrácený objekt také nemá žádné relace nastavené na jiné entity.

Klonovaný objekt může být užitečný pro řešení problémů souvisejících se souběžnými aktualizacemi databáze, zejména při datové vazbě k objektům určitého typu. Další informace najdete v tématu optimistická souběžnost .

Práce se všemi navigacemi entity

EntityEntry.Navigations vrátí hodnotu IEnumerable<T> NavigationEntry pro každou navigaci entity. EntityEntry.References a EntityEntry.Collections udělej to samé, ale omezuje se na odkazy nebo navigaci v kolekci. Dá se použít k provedení akce pro každou navigaci entity. Pokud například chcete vynutit načítání všech souvisejících entit:

foreach (var navigationEntry in context.Entry(blog).Navigations)
{
    navigationEntry.Load();
}

Práce se všemi členy entity

Běžné vlastnosti a navigační vlastnosti mají jiný stav a chování. Proto je běžné zpracovávat navigace a navigace, které nejsou navigačními prvky samostatně, jak je znázorněno v předchozích částech. Někdy ale může být užitečné něco udělat s libovolným členem entity bez ohledu na to, jestli se jedná o běžnou vlastnost nebo navigaci. EntityEntry.Member a EntityEntry.Members jsou k tomuto účelu poskytovány. Příklad:

foreach (var memberEntry in context.Entry(blog).Members)
{
    Console.WriteLine(
        $"Member {memberEntry.Metadata.Name} is of type {memberEntry.Metadata.ClrType.ShortDisplayName()} and has value {memberEntry.CurrentValue}");
}

Spuštění tohoto kódu na blogu z ukázky vygeneruje následující výstup:

Member Id is of type int and has value 1
Member Name is of type string and has value .NET Blog
Member Posts is of type IList<Post> and has value System.Collections.Generic.List`1[Post]

Tip

Ladicí zobrazení sledování změn zobrazuje podobné informace. Zobrazení ladění pro celé sledování změn se generuje z jednotlivých EntityEntry.DebugView sledovaných entit.

Najít a najítsync

DbContext.FindDbSet<TEntity>.Find, DbContext.FindAsync, a DbSet<TEntity>.FindAsync jsou navrženy pro efektivní vyhledávání jedné entity, pokud je jeho primární klíč známý. Nejprve zjistí, jestli je entita již sledována, a pokud ano, vrátí entitu okamžitě. Databázový dotaz se vytvoří pouze v případě, že entita není sledována místně. Představte si například tento kód, který volá funkci Najít dvakrát pro stejnou entitu:

using var context = new BlogsContext();

Console.WriteLine("First call to Find...");
var blog1 = context.Blogs.Find(1);

Console.WriteLine($"...found blog {blog1.Name}");

Console.WriteLine();
Console.WriteLine("Second call to Find...");
var blog2 = context.Blogs.Find(1);
Debug.Assert(blog1 == blog2);

Console.WriteLine("...returned the same instance without executing a query.");

Výstup z tohoto kódu (včetně protokolování EF Core) při použití SQLite je:

First call to Find...
info: 12/29/2020 07:45:53.682 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
      Executed DbCommand (1ms) [Parameters=[@__p_0='1' (DbType = String)], CommandType='Text', CommandTimeout='30']
      SELECT "b"."Id", "b"."Name"
      FROM "Blogs" AS "b"
      WHERE "b"."Id" = @__p_0
      LIMIT 1
...found blog .NET Blog

Second call to Find...
...returned the same instance without executing a query.

Všimněte si, že první volání nenajde entitu místně a proto spustí databázový dotaz. Druhé volání naopak vrátí stejnou instanci bez dotazování databáze, protože je již sledována.

Funkce Najít vrátí hodnotu null, pokud entita s daným klíčem není sledována místně a v databázi neexistuje.

Složené klávesy

Funkce Najít se dá použít také se složenými klíči. Představte si například entitu OrderLine se složeným klíčem, který se skládá z ID objednávky a ID produktu:

public class OrderLine
{
    public int OrderId { get; set; }
    public int ProductId { get; set; }

    //...
}

Složený klíč musí být nakonfigurovaný DbContext.OnModelCreating tak, aby definoval klíčové části a jejich pořadí. Příklad:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<OrderLine>()
        .HasKey(e => new { e.OrderId, e.ProductId });
}

Všimněte si, že OrderId je první částí klíče a ProductId je druhou částí klíče. Toto pořadí se musí použít při předávání hodnot klíče do funkce Najít. Příklad:

var orderline = context.OrderLines.Find(orderId, productId);

Použití ChangeTracker.Entries pro přístup ke všem sledovaným entitám

Zatím jsme přistupovali pouze k jednomu EntityEntry najednou. ChangeTracker.Entries() vrátí EntityEntry pro každou entitu, která je aktuálně sledována DbContext. Příklad:

using var context = new BlogsContext();
var blogs = context.Blogs.Include(e => e.Posts).ToList();

foreach (var entityEntry in context.ChangeTracker.Entries())
{
    Console.WriteLine($"Found {entityEntry.Metadata.Name} entity with ID {entityEntry.Property("Id").CurrentValue}");
}

Tento kód vygeneruje následující výstup:

Found Blog entity with ID 1
Found Post entity with ID 1
Found Post entity with ID 2

Všimněte si, že se vrátí položky pro blogy i příspěvky. Místo toho lze výsledky filtrovat podle konkrétního ChangeTracker.Entries<TEntity>() typu entity pomocí obecného přetížení:

foreach (var entityEntry in context.ChangeTracker.Entries<Post>())
{
    Console.WriteLine(
        $"Found {entityEntry.Metadata.Name} entity with ID {entityEntry.Property(e => e.Id).CurrentValue}");
}

Výstup z tohoto kódu ukazuje, že se vrátí pouze příspěvky:

Found Post entity with ID 1
Found Post entity with ID 2

Použití obecného přetížení také vrací obecné EntityEntry<TEntity> instance. To je to, co umožňuje, aby fluent-like přístup k vlastnosti v tomto příkladu Id .

Obecný typ použitý pro filtrování nemusí být mapovaným typem entity; Místo toho lze použít nemapovaný základní typ nebo rozhraní. Pokud například všechny typy entit v modelu implementují rozhraní definující jejich klíčovou vlastnost:

public interface IEntityWithKey
{
    int Id { get; set; }
}

Toto rozhraní lze použít k práci s klíčem jakékoli sledované entity silným typem. Příklad:

foreach (var entityEntry in context.ChangeTracker.Entries<IEntityWithKey>())
{
    Console.WriteLine(
        $"Found {entityEntry.Metadata.Name} entity with ID {entityEntry.Property(e => e.Id).CurrentValue}");
}

Použití DbSet.Local k dotazování sledovaných entit

Dotazy EF Core se vždy spouštějí v databázi a vrací pouze entity, které byly uloženy do databáze. DbSet<TEntity>.Local poskytuje mechanismus dotazování DbContext pro místní sledované entity.

Vzhledem k tomu DbSet.Local , že se používá k dotazování sledovaných entit, je typické načíst entity do DbContext a pak pracovat s těmito načtenými entitami. To platí zejména pro datové vazby, ale může být užitečné i v jiných situacích. Například v následujícím kódu se databáze nejprve dotazuje na všechny blogy a příspěvky. Metoda Load rozšíření se používá ke spuštění tohoto dotazu s výsledky sledovanými kontextem, aniž by se vrátila přímo do aplikace. (Použití ToList nebo podobné má stejný účinek, ale s režií na vytvoření vráceného seznamu, který zde není potřeba.) Příklad pak používá DbSet.Local přístup k místně sledovaným entitě:

using var context = new BlogsContext();

context.Blogs.Include(e => e.Posts).Load();

foreach (var blog in context.Blogs.Local)
{
    Console.WriteLine($"Blog: {blog.Name}");
}

foreach (var post in context.Posts.Local)
{
    Console.WriteLine($"Post: {post.Title}");
}

Všimněte si, že na rozdíl od ChangeTracker.Entries()funkce vrátí DbSet.Local instance entity přímo. EntityEntry lze samozřejmě vždy získat pro vrácenou entitu voláním DbContext.Entry.

Místní zobrazení

DbSet<TEntity>.Local vrátí zobrazení místně sledovaných entit, které odráží aktuální hodnoty EntityState těchto entit. Konkrétně to znamená, že:

  • Added jsou zahrnuty entity. Všimněte si, že to není případ běžných dotazů EF Core, protože Added entity ještě v databázi neexistují, a proto se nikdy nevrací databázovým dotazem.
  • Deleted entity jsou vyloučeny. Všimněte si, že to opět není případ normálních dotazů EF Core, protože Deleted entity stále existují v databázi, a proto jsou vráceny databázovými dotazy.

To vše znamená, že DbSet.Local se jedná o zobrazení dat, která odrážejí aktuální koncepční stav grafu entit s entitami zahrnutými Added a Deleted vyloučenými entitami. To odpovídá očekávanému stavu databáze po zavolání SaveChanges.

Toto je obvykle ideální zobrazení pro datovou vazbu, protože prezentuje uživateli data tak, jak jim rozumí na základě změn provedených aplikací.

Následující kód ukazuje, že označí jeden příspěvek jako Deleted a pak přidá nový příspěvek, označí ho jako Added:

using var context = new BlogsContext();

var posts = context.Posts.Include(e => e.Blog).ToList();

Console.WriteLine("Local view after loading posts:");

foreach (var post in context.Posts.Local)
{
    Console.WriteLine($"  Post: {post.Title}");
}

context.Remove(posts[1]);

context.Add(
    new Post
    {
        Title = "What’s next for System.Text.Json?",
        Content = ".NET 5.0 was released recently and has come with many...",
        Blog = posts[0].Blog
    });

Console.WriteLine("Local view after adding and deleting posts:");

foreach (var post in context.Posts.Local)
{
    Console.WriteLine($"  Post: {post.Title}");
}

Výstupem tohoto kódu je:

Local view after loading posts:
  Post: Announcing the Release of EF Core 5.0
  Post: Announcing F# 5
  Post: Announcing .NET 5.0
Local view after adding and deleting posts:
  Post: What’s next for System.Text.Json?
  Post: Announcing the Release of EF Core 5.0
  Post: Announcing .NET 5.0

Všimněte si, že odstraněný příspěvek se odebere z místního zobrazení a přidaný příspěvek je zahrnutý.

Přidání a odebrání entit pomocí místního

DbSet<TEntity>.Localvrátí instanci .LocalView<TEntity> Jedná se o implementaci ICollection<T> , která generuje oznámení a reaguje na ně při přidání a odebrání entit z kolekce. (Jedná se o stejný koncept, ale ObservableCollection<T>implementovaný jako projekce stávajících položek sledování změn EF Core, nikoli jako nezávislá kolekce.)

Oznámení místního zobrazení jsou připojená ke sledování změn DbContext, aby místní zobrazení zůstalo synchronizované s DbContext. Konkrétně:

  • Přidání nové entity, která DbSet.Local způsobí, že ji bude sledovat DbContext, obvykle ve Added stavu. (Pokud už entita má vygenerovanou hodnotu klíče, sleduje se jako Unchanged .)
  • Odebrání entity z DbSet.Local důvodů, že bude označena jako Deleted.
  • V kolekci se automaticky zobrazí DbSet.Local entita, která bude sledována dbContextem. Například spuštěním dotazu, aby se přinesly další entity, se místní zobrazení automaticky aktualizuje.
  • Entita označená jako Deleted bude automaticky odebrána z místní kolekce.

To znamená, že místní zobrazení lze použít k manipulaci se sledovanými entitami jednoduše přidáním a odebráním z kolekce. Pojďme například upravit předchozí ukázkový kód tak, aby přidával a odebíral příspěvky z místní kolekce:

using var context = new BlogsContext();

var posts = context.Posts.Include(e => e.Blog).ToList();

Console.WriteLine("Local view after loading posts:");

foreach (var post in context.Posts.Local)
{
    Console.WriteLine($"  Post: {post.Title}");
}

context.Posts.Local.Remove(posts[1]);

context.Posts.Local.Add(
    new Post
    {
        Title = "What’s next for System.Text.Json?",
        Content = ".NET 5.0 was released recently and has come with many...",
        Blog = posts[0].Blog
    });

Console.WriteLine("Local view after adding and deleting posts:");

foreach (var post in context.Posts.Local)
{
    Console.WriteLine($"  Post: {post.Title}");
}

Výstup zůstane beze změny z předchozího příkladu, protože změny provedené v místním zobrazení se synchronizují s DbContext.

Použití místního zobrazení pro datové vazby model Windows Forms nebo WPF

DbSet<TEntity>.Local tvoří základ pro datové vazby k entitám EF Core. Model Windows Forms i WPF ale fungují nejlépe při použití s konkrétním typem upozorňování kolekce, že očekávají. Místní zobrazení podporuje vytváření těchto konkrétních typů kolekcí:

Příklad:

ObservableCollection<Post> observableCollection = context.Posts.Local.ToObservableCollection();
BindingList<Post> bindingList = context.Posts.Local.ToBindingList();

Další informace o datové vazbě WPF s EF Core najdete v tématu Začínáme s WPF a začínáme s model Windows Forms další informace o model Windows Forms datové vazbě s EF Core.

Tip

Místní zobrazení pro danou instanci DbSet se vytvoří lazily při prvním přístupu a pak v mezipaměti. Vytvoření LocalView je rychlé a nepoužívá významnou paměť. Volá ale DetectChanges, což může být pomalé u velkého počtu entit. Kolekce vytvořené ToObservableCollection a ToBindingList také se vytvářejí lazily a pak se ukládají do mezipaměti. Obě tyto metody vytvářejí nové kolekce, které můžou být pomalé a používají spoustu paměti, když jsou zapojeny tisíce entit.