我正在使用代码优先方法,我正在尝试更改EF创建表的方式。我有两个简单的类:
注意:我每次都删除并重新创建数据库。这不会发生在现实世界中,但是对于测试我试图拦截创建并强制EF创建数据库我是如何构想的。
public class Person
{
public int PersonId { get; private set; }
public string Forename { get; set; }
}
public class Officer : Person
{
public int OfficerId { get; private set; }
public bool IsManager { get; set; }
}
在我的OnModelCreating()事件中,我有以下内容:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Person>().HasKey(x => x.PersonId);
modelBuilder.Entity<Person>().ToTable("Person");
modelBuilder.Entity<Officer>().HasKey<int>(x => x.OfficerId);
modelBuilder.Entity<Officer>().ToTable("Officer");
}
问题是在创建数据库时,它将表创建为:
表:人 PersonId INT PK Forename nvarchar(50)
表:官员 PersonId INT PK,FK IsManager BIT OfficerId INT
对我而言,这看起来是错误的,因为它不符合传统的命名约定,即TableNameId。
非常感谢任何帮助。 在此先感谢Onam。
答案 0 :(得分:3)
实体框架忽略了这一行......
modelBuilder.Entity<Officer>().HasKey<int>(x => x.OfficerId);
...因为您无法单独为派生实体定义密钥,仅适用于您在此处完成的基本实体Person
:
modelBuilder.Entity<Person>().HasKey(x => x.PersonId);
然后,此密钥和相应的列名PersonId
将用于基本实体和派生实体的所有表。 Code-First无法为派生表中的键列赋予与基表中相同的名称。
派生实体OfficerId
中的Officer
被视为普通标量属性,它在OfficerId INT
中显示为PK
而不是Officer
。
关于命名约定,您可以说Person
是 PersonId
,因此调用密钥{{1}}可能有意义。嗯,这更像是面向对象而不是关系和表格观点的命名约定。
答案 1 :(得分:1)
你的班级结构有点不正确。理想情况下,你应该让一个抽象类说人,然后从中派生或者只是从官员类中删除OfficerId。否则在军官表中你会将personid作为一个只是一个冗余字段的字段而你将不会使用它。 所以你可以做的是
public class PersonBase {public string ForeName{get; set;}}
public class Person : PersonBase {public int PersonId{get; set;}}
public class Officer : PersonBase{public int OfficerId{get; set;} public bool IsManager{get; set;}}
或者,如果要更改映射的EF字段的列名,可以使用[Column(Name="COLOUMN NAME")]
属性