継承 (リレーショナル データベース)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 コアに実装されます。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 では、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 コアに継承はセットアップだけ (を参照してください継承詳細)。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");
});