4

我正在使用代码优先方法,并且我正在尝试更改 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");
    }

问题是创建我的数据库时,它会将表创建为:

表:Person PersonId INT PK Forename nvarchar(50)

表:Officer PersonId INT PK,FK IsManager BIT OfficeId INT

对我来说,这看起来是错误的,因为它不符合传统的命名约定,即 TableNameId。

非常感谢您对此的任何帮助。在此先感谢,奥南。

4

2 回答 2

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.

关于命名约定,您可能会认为 anOfficer 是 a Person,因此调用 key 可能是有意义的PersonId。嗯,这更像是面向对象的命名约定,而不是关系和表的观点。

于 2013-05-20T19:06:25.520 回答
1

你的班级结构有点不正确。理想情况下,您应该让一个抽象类说人,然后从它派生出来,或者只是从军官类中删除OfficeId。否则在officer表中,您将拥有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")]属性

于 2013-05-20T17:52:42.290 回答