DevralmaInheritance

EF bir .NET tür hiyerarşisini bir veritabanıyla eşleyebilir.EF can map a .NET type hierarchy to a database. Bu, temel ve türetilmiş türleri kullanarak .NET varlıklarınızı kodda her zamanki gibi yazmanızı sağlar ve uygun veritabanı şemasını, sorun sorgularını vb. kullanarak sorunsuz bir şekilde oluşturabilirsiniz. Bir tür hiyerarşisinin nasıl eşlendiğine ilişkin gerçek Ayrıntılar sağlayıcıya bağımlıdır; Bu sayfa, bir ilişkisel veritabanı bağlamında devralma desteğini açıklar.This allows you to write your .NET entities in code as usual, using base and derived types, and have EF seamlessly create the appropriate database schema, issue queries, etc. The actual details of how a type hierarchy is mapped are provider-dependent; this page describes inheritance support in the context of a relational database.

Şu anda EF Core yalnızca hiyerarşi başına tablo (TPH) modelini destekler.At the moment, EF Core only supports the table-per-hierarchy (TPH) pattern. TPH, hiyerarşideki tüm türlerin verilerini depolamak için tek bir tablo kullanır ve her bir satırın hangi türü temsil ettiğini belirlemek için bir Ayrıştırıcı sütunu kullanılır.TPH uses a single table to store the data for all types in the hierarchy, and a discriminator column is used to identify which type each row represents.

Not

EF6 tarafından desteklenen tablo/tür (TPT) ve tablo-somut türü (TPC) EF Core tarafından henüz desteklenmemektedir.The table-per-type (TPT) and table-per-concrete-type (TPC), which are supported by EF6, are not yet supported by EF Core. TPT EF Core 5,0 için planlanmış bir ana özelliktir.TPT is a major feature planned for EF Core 5.0.

Varlık türü hiyerarşisi eşlemeEntity type hierarchy mapping

Kurala göre, EF taban veya türetilmiş türleri otomatik olarak taramaz; Bu, hiyerarşinizdeki bir CLR türünün eşleştirilmesini istiyorsanız, modelinizde açıkça bu türü belirtmeniz gerektiğini gösterir.By convention, EF will not automatically scan for base or derived types; this means that if you want a CLR type in your hierarchy to be mapped, you must explicitly specify that type on your model. Örneğin, bir hiyerarşinin yalnızca temel türü belirtildiğinde, EF Core tüm alt türlerini örtük olarak dahil etmez.For example, specifying only the base type of a hierarchy will not cause EF Core to implicitly include all of its sub-types.

Aşağıdaki örnek, için bir DbSet Blog ve alt sınıfını gösterir RssBlog .The following sample exposes a DbSet for Blog and its subclass RssBlog. BlogBaşka bir alt sınıfa sahipse, modele dahil edilmez.If Blog has any other subclass, it will not be included in the model.

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

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

public class RssBlog : Blog
{
    public string RssUrl { get; set; }
}

Bu model aşağıdaki veritabanı şemasına eşlendi (her satırda hangi Blog türünün depolandığını belirleyen örtük olarak oluşturulmuş ayrıştırıcı sütununu aklınızda bulunur):This model is mapped to the following database schema (note the implicitly-created Discriminator column, which identifies which type of Blog is stored in each row):

image

Not

Veritabanı sütunları, TPH eşlemesi kullanılırken gerektiğinde otomatik olarak null yapılabilir hale getirilir.Database columns are automatically made nullable as necessary when using TPH mapping. Örneğin, normal Blog örnekleri bu özelliğe sahip olmadığından rssurl sütunu null yapılabilir.For example, the RssUrl column is nullable because regular Blog instances do not have that property.

Hiyerarşide bir veya daha fazla varlık için bir DbSet göstermek istemiyorsanız, bu API 'lerin modele dahil olduklarından emin olmak için akıcı API 'yi de kullanabilirsiniz.If you don't want to expose a DbSet for one or more entities in the hierarchy, you can also use the Fluent API to ensure they are included in the model.

İpucu

Kurallara bağlı değilseniz, temel türü açıkça kullanarak belirtebilirsiniz HasBaseType .If you don't rely on conventions, you can specify the base type explicitly using HasBaseType. .HasBaseType((Type)null)Hiyerarşisinden varlık türünü kaldırmak için de kullanabilirsiniz.You can also use .HasBaseType((Type)null) to remove an entity type from the hierarchy.

Ayrıştırıcı yapılandırmasıDiscriminator configuration

Ayrıştırıcı sütununun adını ve türünü ve hiyerarşideki her türü tanımlamak için kullanılan değerleri yapılandırabilirsiniz:You can configure the name and type of the discriminator column and the values that are used to identify each type in the hierarchy:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasDiscriminator<string>("blog_type")
        .HasValue<Blog>("blog_base")
        .HasValue<RssBlog>("blog_rss");
}

Yukarıdaki örneklerde EF, Ayrıştırıcıyı hiyerarşinin temel varlığına örtük bir şekilde bir Gölge Özellik olarak eklemiştir.In the examples above, EF added the discriminator implicitly as a shadow property on the base entity of the hierarchy. Bu özellik, herhangi bir şekilde yapılandırılabilir:This property can be configured like any other:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property("Discriminator")
        .HasMaxLength(200);
}

Son olarak, ayrıştırıcı, varlığınızda düzenli bir .NET özelliğine de eşleştirilebilir:Finally, the discriminator can also be mapped to a regular .NET property in your entity:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasDiscriminator(b => b.BlogType);

    modelBuilder.Entity<Blog>()
        .Property(e => e.BlogType)
        .HasMaxLength(200)
        .HasColumnName("blog_type");
}

Paylaşılan sütunlarShared columns

Varsayılan olarak, hiyerarşideki iki eşdüzey varlık türünün aynı ada sahip bir özelliği varsa, bunlar iki ayrı sütuna eşleştirilir.By default, when two sibling entity types in the hierarchy have a property with the same name, they will be mapped to two separate columns. Ancak, türleri aynıysa aynı veritabanı sütunuyla eşleştirilebilir:However, if their type is identical they can be mapped to the same database column:

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

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .HasColumnName("Url");

        modelBuilder.Entity<RssBlog>()
            .Property(b => b.Url)
            .HasColumnName("Url");
    }
}

public abstract class BlogBase
{
    public int BlogId { get; set; }
}

public class Blog : BlogBase
{
    public string Url { get; set; }
}

public class RssBlog : BlogBase
{
    public string Url { get; set; }
}