In this multi parts series I'll explore how to build inheritance with Entity Framework showing 2 different approaches of inheritance in Entity Framework. Beside that I'll show how to build simple association between 2 entities and show how to provide custom code to retrieve other parts of the relation when inheritance is applied.
My plan not to exceed 3 parts as the subject is not that huge, it is just the demonstration with screen shots that will make the post large that is why I divided it to multi part. I am not good at screen casts beside I don't have a software license to produce one.
Inheritance Types in Entity Framework:
There are 2 models of Inheritance in Entity Framework and they both actually depends on the database design:
- Table-per-Hierarchy Inheritance: One table in storage to maintain data for all the types in an inheritance hierarchy. So basically you have one table in database, but different types in your Entity Model that inherits from a base class and all mapped to that table. This post will focus on this type of Inheritance.
- Table-per-Type Inheritance: Separate table in storage to maintain data for each type in the inheritance hierarchy. That means you might have several tables with one-to-one relationships. Each table is mapped to single Entity in the model. But there is a base Entity that is mapped to the very base table. This is going to be the subject of my next part of this short series. Till then you can watch this video about it.
About the Sample:
The sample I am going to demonstrate here with screen shots is taken from MSDN sample in the links specified above. I found them much clear and easy to demonstrate beside I wasn't able to come out with much simpler sample idea.
How to define a model with Table-per-Hierarchy Inheritance:
At the beginning I'll explore the database design for this subject, and explain why Table-per-Hierarchy must be used to model the inheritance:
This is the only table in hierarchy, but in fact this table store data about different types of persons such as Students, Instructors and Administrators. Those different types of persons are identified by PersonCategory field. Also not all fields are mandatory for each type. For example Students should have EnrollmentDate specified while Instructors should specify their HireDate.
From here we came up with 3 different Entities sharing single table (Table-per-Hierarchy). These Entities are:
- Student: PersonCategory = 1
- Instructor: PersonCategory = 2
- Administrator: PersonCategory = 3
And they are all Person. The existing sample consider a Person itself an instantiatable entity, but for demonstration proposes here Person is just considered an Abstract Entity. Which means a Person must be one of the 3 Entities specified above.
So now the idea is clear why do someone should apply Table-per-Hierarchy inheritance in Entity Framework.
Creating Entity Data Model Wizard:
I'll walk-through the process of creating the Entity Data Model based on the sample database. I'm assuming that you are working on an existing project so I'll skip the project creation step. Screen shots will demonstrate the steps as the following:
- Right Click on the project then Add -> New Item.
- From Add New Item dialog window select ADO.NET Entity Data Model from Template items. Rename to School.edmx or to any other name you like. Click Add
- On Entity Data Model Wizard dialog window make sure that Generate from database is selected. Click Next.
- On next screen, define a new connection to your database or select an existing one. Keep the default settings. Click Next.
- From the next screen, make sure that you select Person table and only that table. Click Finish.
When you are done this should be the simple diagram you'll get:
Creating Sub Entities:
In the following I'll show how to create Entities and make them inherit from Person Entity show above. To create new Entity and make it inherit from Person Entity follow these steps:
- Right Click on the model diagram. From the context menu select Add -> Entity.
- On Add Entity dialog window, set Entity name to Student. Set Base type to Person, this should define the inheritance. Note that once you define Base type, all other properties on the dialog will be disabled. Click Ok.
- Delete EnrollmentDate property on Person Entity as it will be specific Student Entity. Do the same for HireDate as it will be specific for Instructor Entity and AdminDate which will be specific for Administrator Entity.
- Right Click on Student Entity. Select Add -> Scalar Property. Name the property EnrollmentDate. Set its data type on the property window to DateTime.
Repeat the above steps to create the other 2 entities, Administrator and Instructor. Once you finish your model should be similar to this one:
It is time to define mapping and show exactly how you are going to differentiate between Entities using Entity Data Model Mapping. Earlier I specified that PersonCategory is used to identify each Entity. For example one PersonCategory is 1 then that means that this is a Student.
To define mapping for each Entity follow these steps for each one -having Student Entity as Example-:
- Right Click on Student Entity and select Table Mapping. This should display Mapping Details Pan for Student Entity.
- From Mapping Details pan under Tables click on <Add a Table or View> and select Person.
- Click on <Add a Condition> and select PersonCategory. Leave the Operator as "=" and set the Value/Property to 1.
- Under Column Mappings make sure that EnrollmentDate column is mapped to EnrollmentDate property.
Repeat the above steps for both Administrator and Instructor Entities and set the mapping condition to their proper values.
Once you are done It is mandatory to delete the PersonCategory property from Person Entity as it is not needed anymore.
Define An Abstract Class:
As I mentioned earlier, for demonstration I need to set Person Entity as Abstract. However you can still define a mapping for it instead of making it abstract. You should set an Base Entity as Abstract only if you know there will be no direct instantiation from that Entity. For the case here, I plan to have nothing but Student, Instructor and Administrator. There is no simple Person.
To set an Entity as Abstract:
- Right Click on the Person Entity, select Properties form context menu.
- From Properties window and Under Code Generation group, set Abstract property to True. Click Ok on the confirmation message that appears.
Your database design is the primary factor to select between 2 different inheritance models in Entity Framework. In this post I explored the first model Table-per-Hierarchy Inheritance, where only one table is used for all entity type. Many things were running under the hood to generate the CSDL, SSDL and the mapping between both. This XML generated code can be viewed from the ".edmx" file and for more details return to links specified which is pointing to MSDN How-to walk-through. Database script is available with the sample as well as on the original MSND article. On the next part I'll explore hot to implement Table-per-Type Inheritance extending the sample provided in this post.
Download Sample Project.