Freigeben über


Schatten- und Indexereigenschaften

Schatteneigenschaften sind Eigenschaften, die nicht in Ihrer .NET-Entitätsklasse definiert sind, aber für diesen Entitätstyp im EF Core-Modell definiert sind. Der Wert und der Status dieser Eigenschaften werden rein im Change Tracker verwaltet. Schatteneigenschaften sind nützlich, wenn daten in der Datenbank vorhanden sind, die für die zugeordneten Entitätstypen nicht verfügbar gemacht werden sollen.

Indexereigenschaften sind Entitätstypeigenschaften, die von einem Indexer in der .NET-Entitätsklasse unterstützt werden. Auf sie kann mithilfe des Indexers auf den .NET-Klasseninstanzen zugegriffen werden. Außerdem können Sie dem Entitätstyp zusätzliche Eigenschaften hinzufügen, ohne die CLR-Klasse zu ändern.

Fremdschlüssel-Schatteneigenschaften

Schatteneigenschaften werden am häufigsten für Fremdschlüsseleigenschaften verwendet, bei denen sie dem Modell nach Konvention hinzugefügt werden, wenn keine Fremdschlüsseleigenschaft durch Konvention gefunden oder explizit konfiguriert wurde. Die Beziehung wird durch Navigationseigenschaften dargestellt, aber in der Datenbank wird sie durch eine Fremdschlüsseleinschränkung erzwungen, und der Wert für die Fremdschlüsselspalte wird in der entsprechenden Schatteneigenschaft gespeichert.

Die Eigenschaft wird benannt <navigation property name><principal key property name> (die Navigation in der abhängigen Entität, die auf die Hauptentität verweist, wird für die Benennung verwendet). Wenn der Name der Hauptschlüsseleigenschaft mit dem Namen der Navigationseigenschaft beginnt, lautet der Name einfach <principal key property name>. Wenn keine Navigationseigenschaft für die abhängige Entität vorhanden ist, wird der Prinzipaltypname, der mit dem Namen der primären oder alternativen Schlüsseleigenschaft verkettet ist, an seiner Stelle <principal type name><principal key property name>verwendet.

Die folgende Codeauflistung führt beispielsweise dazu, dass eine BlogId Schatteneigenschaft in die Post Entität eingeführt wird:

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

Konfigurieren von Schatteneigenschaften

Sie können die Fluent-API verwenden, um Schatteneigenschaften zu konfigurieren. Nachdem Sie die Zeichenfolgenüberladung Property<TProperty>(String)aufgerufen haben, können Sie alle Konfigurationsaufrufe verketten, die Sie für andere Eigenschaften verwenden würden. Im folgenden Beispiel wird eine Schatteneigenschaft erstellt, da Blog keine CLR-Eigenschaft namens LastUpdated hat:

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

Wenn der an die Property Methode angegebene Name mit dem Namen einer vorhandenen Eigenschaft übereinstimmt (eine Schatteneigenschaft oder eine für die Entitätsklasse definiert), konfiguriert der Code diese vorhandene Eigenschaft, anstatt eine neue Schatteneigenschaft einzuführen.

Zugreifen auf Schatteneigenschaften

Schatteneigenschaftenwerte können über die ChangeTracker API abgerufen und geändert werden:

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

Schatteneigenschaften können in LINQ-Abfragen über die EF.Property statische Methode referenziert werden:

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

Auf Schatteneigenschaften kann nach einer No-Tracking-Abfrage nicht zugegriffen werden, da die zurückgegebenen Entitäten nicht von der Änderungsverfolgung nachverfolgt werden.

Konfigurieren von Indexereigenschaften

Sie können die Fluent-API verwenden, um Indexereigenschaften zu konfigurieren. Nachdem Sie die Methode IndexerPropertyaufgerufen haben, können Sie alle Konfigurationsaufrufe verketten, die Sie für andere Eigenschaften verwenden würden. Im folgenden Beispiel Blog ist ein Indexer definiert, der zum Erstellen einer Indexereigenschaft verwendet wird.

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

Wenn der an die IndexerProperty Methode angegebene Name mit dem Namen einer vorhandenen Indexereigenschaft übereinstimmt, konfiguriert der Code diese vorhandene Eigenschaft. Wenn der Entitätstyp über eine Eigenschaft verfügt, die von einer Eigenschaft der Entitätsklasse unterstützt wird, wird eine Ausnahme ausgelöst, da auf Indexereigenschaften nur über den Indexer zugegriffen werden darf.

Indexereigenschaften können in LINQ-Abfragen über die EF.Property statische Methode wie oben dargestellt oder mithilfe der CLR-Indexereigenschaft referenziert werden.

Entitätstypen der Eigenschaftssammlung

Entitätstypen, die nur Indexereigenschaften enthalten, werden als Eigenschaftsbeutel-Entitätstypen bezeichnet. Diese Entitätstypen verfügen nicht über Schatteneigenschaften, und EF erstellt stattdessen Indexereigenschaften. Derzeit wird nur Dictionary<string, object> als Entitätstyp für Eigenschaftenbeutel unterstützt. Sie muss als shared-type Entitätstyp mit einem eindeutigen Namen konfiguriert werden, und die entsprechende DbSet-Eigenschaft muss mithilfe eines Set-Aufrufs implementiert werden.

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

Entitätstypen des Eigenschaftenbehälters können überall verwendet werden, wo ein normaler Entitätstyp verwendet wird, einschließlich als besitzereigener Entitätstyp. Sie haben jedoch bestimmte Einschränkungen: