5

I am using the code first approach and I am trying to change the behavior of how EF creates my tables. I have two simple classes:

Note: I have my database dropped and recreated every time. This wouldn't happen in the real world but for testing I am trying to intercept the creation and force EF to create the database how I envision it.

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; }
}

In my OnModelCreating() event I have the following:

    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");
    }

Issue is when my database is created it creates the tables as:

Table: Person PersonId INT PK Forename nvarchar(50)

Table: Officer PersonId INT PK, FK IsManager BIT OfficerId INT

To me this looks wrong as it doesn't go by traditional naming conventions, i.e. TableNameId.

Any help on this is much appreciated. Thanks in advance, Onam.

2
  • 1
    Possible duplicate of stackoverflow.com/questions/7278992/… - the answer over there says it currently is not possible to rename the PK for sub-type in a table per type scenario Commented May 20, 2013 at 17:52
  • Thank you, I had a look at that thread you mentioned proved very helpful. Commented May 20, 2013 at 19:22

2 Answers 2

3

Entity Framework ignores this line...

modelBuilder.Entity<Officer>().HasKey<int>(x => x.OfficerId);

...because you cannot define a key separately for a derived entity, only for the base entity Person which you have done here:

modelBuilder.Entity<Person>().HasKey(x => x.PersonId);

This key and the corresponding column name PersonId is then used for all tables of base and derived entities. There is no way with Code-First to give the key column in the derived tables another name than in the base table.

The OfficerId in the derived entity Officer is treated as an ordinary scalar property and it appears in the table as OfficerId INT without being a PK.

Regarding the naming convention you could argue that an Officer is a Person, so it might make sense to call the key PersonId. Well, that's more a naming convention from the object oriented rather than the relational and table viewpoint.

Sign up to request clarification or add additional context in comments.

Comments

1

your class structure is a little incorrect. ideally you should make an abstract class say person and then derive from it or just remove the OfficerId from the officer class. otherwise in the officer table you will have personid as a field which is just a redundant field and you will have no use of it. so what you can do instead is

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;}}

alternatively for changing column name of a mapped EF field you can use [Column(Name="COLOUMN NAME")] attribute

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.