Właściwości cienia i indeksatora

Właściwości w tle to właściwości, które nie są zdefiniowane w klasie jednostek platformy .NET, ale są zdefiniowane dla tego typu jednostki w modelu EF Core. Wartość i stan tych właściwości są utrzymywane wyłącznie w trackerze zmian. Właściwości w tle są przydatne, gdy w bazie danych znajdują się dane, które nie powinny być uwidocznione na mapowanych typach jednostek.

Właściwości indeksatora to właściwości typu jednostki, które są wspierane przez indeksator w klasie jednostek platformy .NET. Dostęp do nich można uzyskać przy użyciu indeksatora w wystąpieniach klas platformy .NET. Umożliwia również dodawanie dodatkowych właściwości do typu jednostki bez zmiany klasy CLR.

Właściwości w tle klucza obcego

Właściwości w tle są najczęściej używane dla właściwości klucza obcego, gdzie są dodawane do modelu zgodnie z konwencją, gdy żadna właściwość klucza obcego nie została znaleziona zgodnie z konwencją lub jawnie skonfigurowana. Relacja jest reprezentowana przez właściwości nawigacji, ale w bazie danych jest wymuszana przez ograniczenie klucza obcego, a wartość kolumny klucza obcego jest przechowywana w odpowiedniej właściwości w tle.

Właściwość zostanie nazwana <navigation property name><principal key property name> (nawigacja w jednostce zależnej, która wskazuje jednostkę główną, jest używana do nazewnictwa). Jeśli nazwa właściwości klucza głównego zaczyna się od nazwy właściwości nawigacji, nazwa będzie tylko nazwą <principal key property name>. Jeśli nie ma właściwości nawigacji w jednostce zależnej, główna nazwa typu połączona z nazwą właściwości klucza podstawowego lub alternatywnego jest używana w jego miejscu <principal type name><principal key property name>.

Na przykład następująca lista kodu spowoduje wprowadzenie BlogId właściwości w tle do Post jednostki:

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

Konfigurowanie właściwości w tle

Aby skonfigurować właściwości w tle, możesz użyć interfejsu API Fluent. Po wywołaniu przeciążenia Property<TProperty>(String)ciągu programu można połączyć dowolne wywołania konfiguracji dla innych właściwości. W poniższym przykładzie, ponieważ Blog nie ma właściwości CLR o nazwie LastUpdated, tworzona jest właściwość w tle:

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

Jeśli nazwa podana do Property metody jest zgodna z nazwą istniejącej właściwości (właściwość w tle lub zdefiniowana w klasie jednostki), kod skonfiguruje tę istniejącą właściwość zamiast wprowadzać nową właściwość w tle.

Uzyskiwanie dostępu do właściwości w tle

Wartości właściwości w tle można uzyskać i zmienić za pomocą interfejsu ChangeTracker API:

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

Właściwości w tle można odwoływać się do zapytań LINQ za pośrednictwem metody statycznej EF.Property :

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

Nie można uzyskać dostępu do właściwości w tle po kwerendzie bez śledzenia, ponieważ zwrócone jednostki nie są śledzone przez monitor zmian.

Konfigurowanie właściwości indeksatora

Aby skonfigurować właściwości indeksatora, możesz użyć interfejsu API Fluent. Po wywołaniu metody IndexerPropertymożna połączyć dowolne wywołania konfiguracji dla innych właściwości. W poniższym przykładzie Blog zdefiniowano indeksator i zostanie użyty do utworzenia właściwości indeksatora.

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

Jeśli nazwa podana w metodzie IndexerProperty jest zgodna z nazwą istniejącej właściwości indeksatora, kod skonfiguruje tę istniejącą właściwość. Jeśli typ jednostki ma właściwość, która jest wspierana przez właściwość klasy jednostki, zgłaszany jest wyjątek, ponieważ właściwości indeksatora muszą być dostępne tylko za pośrednictwem indeksatora.

Właściwości indeksatora można odwoływać w zapytaniach LINQ za pośrednictwem EF.Property metody statycznej, jak pokazano powyżej lub przy użyciu właściwości indeksatora CLR.

Typy jednostek torby właściwości

Typy jednostek, które zawierają tylko właściwości indeksatora, są nazywane typami jednostek torby właściwości. Te typy jednostek nie mają właściwości w tle, a zamiast tego program EF tworzy właściwości indeksatora. Obecnie jest obsługiwana tylko Dictionary<string, object> jako typ jednostki worka właściwości. Należy go skonfigurować jako typ jednostki typu współużytkowanego o unikatowej nazwie, a odpowiednią DbSet właściwość należy zaimplementować przy użyciu wywołania Set .

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 jednostek torby właściwości mogą być używane wszędzie tam, gdzie używany jest typ jednostki normalnej, w tym jako typ jednostki należącej. Jednak mają pewne ograniczenia: