繼承 (關聯式資料庫)Inheritance (Relational Database)

注意

本節中的組態一般適用於關聯式資料庫。The configuration in this section is applicable to relational databases in general. 當您因共用 Microsoft.EntityFrameworkCore.Relational 套件而安裝關聯式資料庫提供者時,這裡顯示的擴充方法會變成可用。The extension methods shown here will become available when you install a relational database provider (due to the shared Microsoft.EntityFrameworkCore.Relational package).

EF 模型中的繼承用來控制如何在實體類別中的繼承表示在資料庫中。Inheritance in the EF model is used to control how inheritance in the entity classes is represented in the database.

注意

目前,只有每個階層的資料表 (TPH) 模式中實作的 EF Core。Currently, only the table-per-hierarchy (TPH) pattern is implemented in EF Core. 其他常見的模式資料表每個類型 (TPT) 等資料表的個別實體類型 (TPC) 尚無法使用。Other common patterns like table-per-type (TPT) and table-per-concrete-type (TPC) are not yet available.

慣例Conventions

依照慣例,繼承將會使用每個階層資料表 (TPH) 模式對應。By convention, inheritance will be mapped using the table-per-hierarchy (TPH) pattern. TPH 使用單一資料表儲存在階層中所有類型的資料。TPH uses a single table to store the data for all types in the hierarchy. 鑑別子資料行用來識別每個資料列都代表哪種類型。A discriminator column is used to identify which type each row represents.

EF Core 只會設定繼承,如果兩個或多個繼承的型別會明確地包含在模型中 (請參閱繼承如需詳細資訊)。EF Core will only setup inheritance if two or more inherited types are explicitly included in the model (see Inheritance for more details).

以下是範例,示範一個簡單的繼承案例及使用 TPH 模式關聯式資料庫資料表中儲存的資料。Below is an example showing a simple inheritance scenario and the data stored in a relational database table using the TPH pattern. 鑑別子資料行會識別哪一種部落格會儲存在每個資料列。The Discriminator column identifies which type of Blog is stored in each row.

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

影像

資料註釋Data Annotations

若要設定繼承,您無法使用資料註解。You cannot use Data Annotations to configure inheritance.

Fluent APIFluent API

您可以使用 fluent 應用程式開發的應用程式開發介面來設定的名稱和類型鑑別子資料行以及用來識別階層中的每個類型的值。You can use the Fluent API to configure the name and type of the discriminator column and the values that are used to identify each type in the hierarchy.

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

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

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

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

設定鑑別子屬性Configuring the discriminator property

在上述範例中,鑑別子會建立為陰影屬性在階層的基底實體。In the examples above, the discriminator is created as a shadow property on the base entity of the hierarchy. 因為這是模型中的屬性,它可以就像其他屬性設定。Since it is a property in the model, it can be configured just like other properties. 例如,若要使用預設值,依慣例鑑別子而設定的最大長度:For example, to set the max length when the default, by-convention discriminator is being used:

modelBuilder.Entity<Blog>()
    .Property("Discriminator")
    .HasMaxLength(200);

鑑別子也可以對應至實際的 CLR 屬性實體中。The discriminator can also be mapped to an actual CLR property in your entity. 例如: For example:

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

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .HasDiscriminator<string>("BlogType");
    }
}

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

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

結合這兩個條件也可同時將鑑別子對應到實際屬性並加以設定:Combining these two things together it is possible to both map the discriminator to a real property and configure it:

modelBuilder.Entity<Blog>(b =>
{
    b.HasDiscriminator<string>("BlogType");

    b.Property(e => e.BlogType)
        .HasMaxLength(200)
        .HasColumnName("blog_type");
});