継承 (リレーショナル データベース)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.

注意

現時点では、EF Core での table-per-hierarchy (TPH) パターンのみが実装されます。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

慣例により、継承を-table-per-hierarchy (TPH) パターンを使用してマップされます。By convention, inheritance will be mapped using the table-per-hierarchy (TPH) pattern. TPH は、階層内のすべての種類のデータを格納するのに 1 つのテーブルを使用します。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.

2 つまたは複数の継承された型がモデルで明示的に含まれている場合は、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 API を使用して、名前と識別子列と、階層内の各型を識別するために使用される値の型を構成することができます。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; }
}

これら 2 つを組み合わせることは、識別子を実際のプロパティにマップし、構成の両方にできます。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");
});