我在使用 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上定义了外键。我做错了什么?我不想要这两列。
您的表包含更多未定义的列:如果您不想映射派生类型,也不应映射Val1
、Val2
和 Discriminator
。但是,如果不映射这些类型,则永远无法从 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; }