Code First Inheritance

Topics: EF Runtime
Oct 11, 2013 at 2:52 PM
Hi, i'm having some issues trying to used mixed inheritance strategies with EF 6.0 RC1 & Code First.
I would like to know if it's possible to achieve this:
abstract     MessageBase       --> Message table
non-abstract Message           --> Message table when MessageType == 1
non-abstract Comment          --> Message table when MessageType == 2
non-abstract SuperMessage  --> SuperMessage table
Coordinator
Oct 14, 2013 at 5:08 PM
What is the base class of each of these types? Especially curious about SuperMessage, since 'super class' is a synonym of 'base class'

Thanks,
Diego
Oct 14, 2013 at 9:36 PM
Hi Diego,

All classes (included SuperMessage) derive from MessageBase, and MessageBase derive from nothing.
Coordinator
Oct 23, 2013 at 1:05 AM
Hello iLMaX,

Sorry for not responding to this earlier. I looked at this scenario and here are a few data points that might help you:

The hybrid mapping scenario in which you have a single entity mapped to a table and the rest of its inheritance hierarchy mapped to a different table is explicitly disabled, i.e. when we hit a scenario like this in Code First we throw an exception:

_The type 'X' cannot be mapped as defined because it maps inherited properties from types that use entity splitting or another form of inheritance. Either choose a different inheritance mapping strategy so as to not map inherited properties, or change all types in the hierarchy to map inherited properties and to not use splitting.
_

Code First currently doesn't contain the logic that would be necessary to handle this kind of scenario and we haven't heard customers asking for this to be supported that much.

Even before you hit this exception you might run into other issues. For instance we have a bug in EF 5 and EF 6 that prevents some scenarios with abstract base classes from working. This bug has been fixed and the fix is included in our nightly builds. There is another bug that prevents key columns from being created as IDENTITY in similar scenarios.

One possible workaround that might work for your particular scenario is to avoid including the abstract base class in the model. In order to do this you have to make sure that:
  • You do not include a property of type DbSet<MessageBase> on your DbContext
  • You don't call modelBuilder.Entity<MessageBase>() in the OnModelCreating method (also you can choose to call modelBuilder.Ignore<MessageBase>() explicitly)
  • You don't have any navigation properties of type MessageBase in types that are included in the model
The reason this approach works is that when the abstract base class is not included in the model EF can treat the types in the hierarchy as completely independent types.

Hope this helps,
Diego
Marked as answer by iLMaX on 10/23/2013 at 1:06 AM
Oct 23, 2013 at 9:05 AM
Thank you Diego,

Got it.

Regards, Max