Vlastnosti stínu a indexeru

Stínové vlastnosti jsou vlastnosti, které nejsou definovány ve vaší třídě entity .NET, ale jsou definované pro tento typ entity v modelu EF Core. Hodnota a stav těchto vlastností jsou udržovány čistě v nástroji Change Tracker. Stínové vlastnosti jsou užitečné v případě, že data v databázi, která by neměla být vystavena na mapovaných typech entit.

Vlastnosti indexeru jsou vlastnosti typu entity, které jsou podporovány indexerem ve třídě entity .NET. K nim lze přistupovat pomocí indexeru v instancích tříd .NET. Umožňuje také přidat další vlastnosti do typu entity beze změny třídy CLR.

Stínové vlastnosti cizího klíče

Stínové vlastnosti se nejčastěji používají pro vlastnosti cizího klíče, kde se přidají do modelu konvencí, pokud nebyla nalezena žádná vlastnost cizího klíče konvencí nebo nakonfigurovaná explicitně. Relace je reprezentována navigačními vlastnostmi, ale v databázi je vynucena omezením cizího klíče a hodnota pro sloupec cizího klíče je uložena v odpovídající stínové vlastnosti.

Vlastnost bude pojmenována <navigation property name><principal key property name> (navigace na závislé entitě, která odkazuje na hlavní entitu, se používá pro pojmenování). Pokud název vlastnosti hlavního klíče začíná názvem navigační vlastnosti, bude název pouze <principal key property name>. Pokud u závislé entity neexistuje žádná navigační vlastnost, použije se na svém místě <principal type name><principal key property name>název hlavního typu zřetězený s názvem vlastnosti primárního nebo alternativního klíče.

Například následující výpis kódu způsobí BlogId , že se do entity zavádí Post stínová vlastnost:

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    // Since there is no CLR property which holds the foreign
    // key for this relationship, a shadow property is created.
    public Blog Blog { get; set; }
}

Konfigurace vlastností stínu

Ke konfiguraci vlastností stínu můžete použít rozhraní Fluent API . Jakmile zavoláte přetížení Property<TProperty>(String)řetězce , můžete zřetězit libovolná volání konfigurace, která byste pro jiné vlastnosti. V následující ukázce, protože Blog nemá žádnou vlastnost CLR s názvem LastUpdated, stínová vlastnost je vytvořena:

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property<DateTime>("LastUpdated");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Pokud název zadaný metodě Property odpovídá názvu existující vlastnosti (stínová vlastnost nebo vlastnost definovaná ve třídě entity), kód nakonfiguruje tuto existující vlastnost místo zavedení nové stínové vlastnosti.

Přístup ke stínovým vlastnostem

Hodnoty stínových vlastností lze získat a změnit prostřednictvím ChangeTracker rozhraní API:

context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now;

Stínové vlastnosti lze odkazovat v dotazech LINQ prostřednictvím EF.Property statické metody:

var blogs = context.Blogs
    .OrderBy(b => EF.Property<DateTime>(b, "LastUpdated"));

Ke stínovým vlastnostem nelze získat přístup po dotazu bez sledování, protože vrácené entity sledování změn nesledují.

Konfigurace vlastností indexeru

Ke konfiguraci vlastností indexeru můžete použít rozhraní Fluent API. Jakmile zavoláte metodu IndexerProperty, můžete zřetězit libovolná volání konfigurace, která byste zadali pro jiné vlastnosti. V následující ukázce Blog je definovaný indexer a použije se k vytvoření vlastnosti indexeru.

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>().IndexerProperty<DateTime>("LastUpdated");
    }
}

public class Blog
{
    private readonly Dictionary<string, object> _data = new Dictionary<string, object>();
    public int BlogId { get; set; }

    public object this[string key]
    {
        get => _data[key];
        set => _data[key] = value;
    }
}

Pokud název zadaný metodě IndexerProperty odpovídá názvu existující vlastnosti indexeru, kód nakonfiguruje tuto existující vlastnost. Pokud typ entity má vlastnost, která je podporována vlastností třídy entity, je vyvolána výjimka, protože vlastnosti indexeru musí být přístupné pouze prostřednictvím indexeru.

Na vlastnosti indexeru lze odkazovat v dotazech LINQ prostřednictvím EF.Property statické metody, jak je znázorněno výše, nebo pomocí vlastnosti indexeru CLR.

Typy entit kontejneru vlastností

Typy entit, které obsahují pouze vlastnosti indexeru, se označují jako typy entit kontejneru vlastností. Tyto typy entit nemají stínové vlastnosti a EF místo toho vytvoří vlastnosti indexeru. V současné době se podporuje pouze Dictionary<string, object> jako typ entity kontejneru vlastností. Musí být nakonfigurován jako typ entity sdíleného typu s jedinečným názvem a odpovídající DbSet vlastnost musí být implementována Set pomocí volání.

internal class MyContext : DbContext
{
    public DbSet<Dictionary<string, object>> Blogs => Set<Dictionary<string, object>>("Blog");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.SharedTypeEntity<Dictionary<string, object>>(
            "Blog", bb =>
            {
                bb.Property<int>("BlogId");
                bb.Property<string>("Url");
                bb.Property<DateTime>("LastUpdated");
            });
    }
}

Typy entit v pytli vlastností lze použít všude, kde se používá normální typ entity, včetně typu vlastněné entity. Mají však určitá omezení: