The Minimalist Guide to Entity Framework Code First (Invalid column name Discriminator)

Why am I getting Invalid column name "Discriminator​" when I am running my code? 

Recently I ran into an interesting little error with entity framework. I was usually a database first kind of guy, but have recently been working on some code first systems and mixing the two approaches with each other to get the best of both world

Why am I getting Invalid column name "Discriminator​" when I am running my code? 

Recently I ran into an interesting little error with entity framework. I was usually a database first kind of guy, but have recently been working on some code first systems and mixing the two approaches with each other to get the best of both worlds. 

So in this particular instance what happened was that we were using an existing database but the entity framework was done using the code first approach, so there is no automatic generation of the classes. We had some inheritance between some of the entities and everything was going good until we started debugging and we got one of those dreaded errors that a column name was not found. So our first question was did we add some random column to one of our classes without realizing it, and now it does not match up to the existing SQL database? Since we couldn't find anything of the kind I had to dig a bit deeper and do some research. It turns out that there are three different ways to setup entity framework code first models/classes and how they all relate to each other.

 

  • Table per type: With this approach each class will have a corresponding table, for example, the class Client will have a table Client and the subclass ClientProfile will have its own table, but the shared properties will stay in the table representing the class, in other words the subclass table will not contain the properties of the base class. Hence this can slow down queries as it now needs to join the two tables to get the complete subclass.
modelBuilder.Entity().ToTable("Client");
modelBuilder.Entity().ToTable("ClientProfile");
  • Table per hierarchy​: Here we have the case where the base class and the subclass will both be merged into the same table, that would mean the BaseEntity table will have all the properties of the BaseEntity, Client and ClientProfile classes. It will also contain an extra field called "Discriminator" which is used to determine what row of data maps to what kind of class.
modelBuilder.Entity()
  .Map(m => m.Requires("Discriminator").HasValue("F"))
  .Map(m => m.Requires("Discriminator").HasValue("I"));
  • Table per concrete type: With this approach each class will have its own table and also include field for all the properties of the base classes. Which would mean that Client gets a table and ClientProfile gets its own table but also all the fields from the Client table.
modelBuilder.Entity().Map(m => {
              m.MapInheritedProperties();
              m.ToTable("Funds"); 
}); 
modelBuilder.Entity().Map(m => {
              m.MapInheritedProperties();
              m.ToTable("InvestorFunds"); 
});

 

In the end we wanted to use TPT but we forgot to setup our mappings correctly in the modelBuilder and entity framework the assumes that you wanted to use TPH. What the best approach to use is, is up for debate and will boil down to your specific system. At least now you know what this error means and why you are receiving it.

Thanks for reading, like us on Facebook or follow us on Twitter @yotta_systems for the latest updates.



Related posts