.Net Core Guide To Code First Inheritance Patterns
By: Dulip Bataogoda
Tags: Entity Framework, Entity Framework Core, Aspnetcore, Net Core

As a developer in .Net sometimes it can be overwhelming to find a simple guide to something when learning. I faced this problem when starting with .net core as there is so much variations of how things could be done. So here is a post summarizing the details I found out when it come to using code first inheritance in .Net core.

Introduction

So you have a UML schema like this below, there are 3 classes User, Student and Teacher.

Simple Class Diagram we will use as an example

User is an abstract class and Student and Teacher are the concrete implementations of it. So how do we represent this in our database? No worries let the ORM handle it right? Well not so fast…

How Entity Framework Core handles it

Entity framework core maps the entire class hierarchy to a single table(Users in this example) with null-able column values for child class properties. So the Users table will contain columns for all the properties for User class, Student class and Teachers class. Also there is a ‘Discriminator’ column which will identify whether the row data is for a Student or Teacher. When we add a data migration it will create something like this:

User table in Postgres after we add a migration

This way of handling hierarchy is know as Table per Hierarchy (TPH) and currently this is the only pattern that EF core supports( Plans of adding other patterns are quite some time away as they are planned in EF core version 5.0, while the current stable release is 3.1). While it is nice to have all the data in one table it does violate the 3rd normalization form.

Other Ways of Doing This

Other than TPH there are two other patterns to address inheritance in object to relation mapping.

Table per Type (TPT)

Every class in the hierarchy including abstract classes are mapped separately to their own tables. So a Users table will be created along with Students and Teachers tables. Users table will only have it’s own properties and no child class properties mapped to it.

Users table now

TPT also means that the child class tables will contain columns for only their own properties(no parent class properties) and a foreign key referring to the parent class Id.

Students table that contain only two properties and UserId

Similarly Teachers table will only contain columns for salary, SubjectId and UserId.

Table per Concrete Class (TPC)

This pretty straight forward method of mapping inheritance. In TPC we do not map abstract classes, we map only the concrete classes to tables. And we map all properties of that class including inherited ones to it’s table.

So in our example we would have 2 tables Students with all of properties of Student class including Id, Name and Email of it’s parent User class in one table. Similarly a Teachers table with all of the properties of Teacher class including the properties of the parent class User.

Entity Framework 6.3

In September 2019 Entity Framework 6.3 version was released and one of the main new features was adding support for .Net Core applications. So applications with .Net Core 3.0 or higher can use Entity Framework instead of Entity Framework core.

This means that unlike when using EF Core you can now use all 3 types of the inheritance methods we discussed. It is important to note tho that the default pattern is TPH even in Entity Framework 6.3 so if you want to use TPT or TPC you do need to manually configure it to use these patterns.

Entity Framework for .Net core is still new so there are limitations when using this(full blog post in here https://devblogs.microsoft.com/dotnet/announcing-entity-framework-6-3-preview-with-net-core-support/ )

NHibernate

Although not provided by Microsoft themselves, this is also a popular ORM for .Net core. With NHibernate it is possible to use all 3 approaches for inheritance mapping. But NHibernate is a bit more complex comparatively.

References

This post is suppose to be a short-ish guide so could not include all the details. If you want to read more on Inheritance mapping here are 3 great blog post.