TPH 继承外键的实体框架代码优先在数据库表中添加其他列



我在使用 TPH 时遇到了 EF Code First 的问题。我在表中获得了模型中没有的另外两列。

我有一个类结构如下:

 public class TestBase
    {
        public int Id { get; set; }

        public string Name { get; set; }
        [ForeignKey("TestMaster")]
        public string TestMaster_Id { get; set; }
        public TestMaster TestMaster { get; set; }
    }
    public class TestInherit1 : TestBase
    {
        public string Val1 { get; set; }
    }
    public class TestInherit2 : TestBase
    {
        public string  val2 { get; set; }
    }
    public class TestMaster
    {
        [Key]
        public string Id { get; set; }
        public virtual ICollection<TestInherit1> Inherit1List { get; set; }
        public virtual ICollection<TestInherit2> Inherit2List { get; set; }
    }

在DBContext中,我有以下内容:

    public DbSet<TestMaster> TestMaster
    {
        get;
        set;
    }
    public DbSet<TestBase> TestBase
    {
        get;
        set;
    }
    [NotMapped]
    public DbSet<TestInherit1> TestInherit1
    {
        get;
        set;
    }
    [NotMapped]
    public DbSet<TestInherit2> TestInherit2
    {
        get;
        set;
    }

以下是 EF 生成的表结构:

[TestBases]
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NULL,
    [TestMaster_Id] [nvarchar](128) NULL,
    [Val1] [nvarchar](max) NULL,
    [val2] [nvarchar](max) NULL,
    [Discriminator] [nvarchar](128) NOT NULL,
    [TestMaster_Id1] [nvarchar](128) NULL,
    [TestMaster_Id2] [nvarchar](128) NULL
[TestMasters](
    [Id] [nvarchar](128) NOT NULL

如果您查看 TestBases 表,则还有两TestMaster_id1和TestMaster_Id2生成的另外列,这些列未在类中定义。 EF 正在插入这两列。我已经在列TestMaster_Id上定义了外键。我做错了什么?我不想要这两列。

您的表包含更多未定义的列:如果您不想映射派生类型,也不应映射Val1Val2Discriminator。但是,如果不映射这些类型,则永远无法从 EF 获取这些实例,并且永远无法将该实例存储到 EF。

您的NotMapped属性使用不正确。必须在实体类型或实体类型中的属性上声明它。此外,如果不想映射派生类型,则不应为它们创建DbSet属性。

该属性的正确用法是:

[NotMapped]
public class TestInherit1 : TestBase
{
    public string Val1 { get; set; }
}

或:

[NotMapped]
public virtual ICollection<TestInherit1> Inherit1List { get; set; }

目前,您的实体已映射,这也是您获得两个新外键的原因 - 您将导航属性定义为派生类型。它们中的每一个都需要自己的外键,因为 EF 无法重新定义派生类中父属性的映射。

如果只想在父实体中声明单个外键,则必须仅为父实体定义单个导航属性:

public virtual ICollection<TestBase> TestList { get; set; }

最新更新