2

以下のサンプルでは、​​CTP は User クラス プロパティのみを考慮しますが、Users テーブルに含まれる基本クラス プロパティを想定しています。

CTP に基本クラスのプロパティが含まれていることを伝える方法はありますか? または、代替ソリューションは何ですか?

class PersonDBContext : DbContext
{
    public DbSet<User> UserSet { get; set; }
}
class Person
{
    public string Firstname { get; set; }
    public string SurName { get; set; }
}
class User : Person
{
    public int UserId { get; set; }
    public string CreatedOn { get; set; }
}
4

1 に答える 1

3

DbSet<User>これは、の代わりに DbContext で宣言したためですDbSet<Person>。EF コードには、継承に関して最初に到達可能性の概念があります。これは基本的に、基本クラスのセットをコンテキストに配置すると、そのサブクラスをすべて見つけて含めることを意味します。

ここにはもう 1 つの問題があります。Personクラスの主キーを指定していないため、EF は Code First 規則に基づいて主キーを推測できませんでした。デフォルトでは、EF はモデルの継承をデータベースの TPH (Type Per Hierarchy) にマップし、サブクラスは、モデルのサブクラス (つまり UserId) に配置された基本クラスからキーを継承します。

これを修正するには、まず DbContext の DbSet を型に変更してから、次のように基本クラスPersonに移動してそれをKeyにする必要があります。UserIdPerson

public class Person 
{
    [Key]
    public int UserId { get; set; }

    public string Firstname { get; set; }
    public string SurName { get; set; }
}

public class User : Person 
{        
    public string CreatedOn { get; set; }
}

public class PersonDBContext : DbContext 
{
    public DbSet<Person> UserSet { get; set; }        
}

このモデルは、両方のクラスのすべての列を持つ次の DB スキーマになります (複数形のサポートに注意してください)。

代替テキスト

Code First で TPH を TPT (Table Per Hierarchy) に変更する方法:

私が言ったように、慣例により、EF コードは最初に TPH を使用して継承をデータベースにマップし、それを TPT に変更するには、Fluent API を使用して規則をオーバーライドする必要があります。

public class StackOverflowContext : DbContext
{
    public DbSet<Person> Persons { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>().MapHierarchy(p => new
        {
            p.UserId,
            p.Firstname,
            p.SurName,
        })
        .ToTable("Person");

        modelBuilder.Entity<User>().MapHierarchy(u => new
        {
            u.UserId,
            u.CreatedOn
        })
        .ToTable("User");
    }
}

このモデルは、次の DB スキーマになります。

代替テキスト

Code First で TPH を TPC (Concrete Type ごとのテーブル) に変更する方法:

Table per Concrete Class には、各クラスのテーブルがあり、それらの各テーブルには、そのタイプのすべてのプロパティの列があります。

このコードを以下に示します。2 つのテーブル間に外部キーがなく、一意のキーを提供する必要があるため、主キー プロパティの ID をオフにしていることに注意してください。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>().Property(p => p.UserId)
    .StoreGeneratedPattern = System.Data.Metadata.Edm.StoreGeneratedPattern.None;

    modelBuilder.Entity<Person>().MapSingleType(p => new
    {
        p.UserId,
        p.Firstname,
        p.SurName,
    })
    .ToTable("Person");

    modelBuilder.Entity<User>().MapSingleType(u => new
    {
        u.UserId,
        u.CreatedOn,
        u.Firstname,
        u.SurName,
    })
    .ToTable("User");
}

このモデルは、次の DB スキーマになります。 代替テキスト

于 2010-12-06T02:40:08.170 に答える