3

This problem will be explained around 3 classes: Account, IndividualAccount, and Doctor:

  • First two classes are abstract
  • IndividualAccount is Account's subclass
  • Doctor is IndividualAccount's subclass

The first layer of inheritance (between Account and IndividualAccount) is being implemented with Table Per Type methodology. The second layer of inheritance (between IndividualAccount and Doctor) is being implamented with Table per Hierarchy methodology.

The Fluent API configurations is as following:

class AccountConfiguration : EntityTypeConfiguration<Account>
  public AccountConfiguration()
  {
    HasKey(x => x.Id);
    ...
  }
}

class IndividualAccountConfiguration : EntityTypeConfiguration<IndividualAccount>
{
  public IndividualAccountConfiguration()
  {
    ToTable("IndividualAccounts");
    ...
  }
}

class DoctorConfiguration : EntityTypeConfiguration<Doctor>
{
  public DoctorConfiguration()
  {
    ...
  }
}

What we expect from this configuration is to have two tables: first one storing an Id and common properties to all users (e.g. username and password) and the second one storing properties common to all individuals (e.g. name and phone number). Moreover The second table will have a discriminator field distinguishing between Doctors and other type of Individuals we may have in our domain.

The problem arises when I try to get a Doctor by it's id. An exception will be thrown alleging that numerous columns are invalid, the most important one of them being:
Invalid column name 'Discriminator'.\r\n

To my surprise if I place [Table("IndividualAccounts")] above IndividualAccount class definition, problem will be resolved. But I have already set the table name in configuration (Fluent API). Why should I use the annotation in addition to the Fluent API?

Update
In presence of Annotation, Doctor's properties are placed in IndividualAccounts table which indeed is what we expected. But If I remove the annotation, a new migration will be created trying to move those fields to the base table Account!

mdoust
  • 429
  • 1
  • 4
  • 20

1 Answers1

1

To my surprise if I place [Table("IndividualAccounts")] above IndividualAccount class definition, problem will be resolved. But I have already set the table name in configuration (Fluent API). Why should I use the annotation in addition to the Fluent API?

No the problem is not solved the problem now is hidden. Just check it out with SSM, IndividualAccounts table dose not contains Discriminator column!

ToTable("IndividualAccounts");

throws UnsupportedHybridInheritanceMapping exception, just enable all exceptions then you will get:

More info:

Multiple inheritance with Entity Framework TPC


I have modified my classes so that now I can see also the discriminator.

Next time please post your classes with the question. More info: How to create a Minimal, Complete, and Verifiable example

If you use the below line code, this will disable the convention exception but you will get another kind of problmes later:

modelBuilder.Conventions.Remove<MappingInheritedPropertiesSupportConvention>();

The problem EF try to create TPC and not TPT I will get contact with EF-Team and give you a feedback.

Community
  • 1
  • 1
Bassam Alugili
  • 16,345
  • 7
  • 52
  • 70
  • Thanks for your response. With regards to the tables not being configured as I desired, I checked them again and they are indeed configured as I have explained above, i.e. the IndividualAccounts table does contains the Discriminator column and whole application works fine around it. With regards to having a simpler design, We have considered many alternative and this one was more suitable for our requirements. – mdoust Sep 05 '16 at 20:12
  • @mdoust post please your classes and your DbContext and your complete DbConfigurations, something is missing. I have create the entities exaclty as your description but by me the Discriminator column is missing !? – Bassam Alugili Sep 06 '16 at 07:32