Click here to Skip to main content
Click here to Skip to main content

Tagged as

Inheritance in Entity Framework: Table per Hierarchy

, 11 Jul 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
This is the first article demonstrated inheritance in Entity Framework. In this article I have implemented the Table per Hierarchy approach.

Introduction

This is the Entity Framework article series. In our previous two articles we learned various approaches to working with Entity Framework and various strategies to handle a database in a code first approach. You can read it here:

In this article we will learn to tackle inheritance in Entity Framework. If you are not clear on the aim of the article, the following should help explain it for you:

We know that inheritance is a beautiful concept in Object Oriented programming and it provides the concept of re-usability, which is one of the most important practices of software design principal. OK, so we will implement inheritance at the class level, that’s fine, but how will we implement it at the DB level? As a rule, we know the derive class contains all the properties of the base class, so will the derive class table contain all the properties of the base class table?

We will learn that stuff in this article along with next two articles. There are three approaches in Entity Framework level to tackle inheritance in the code level.

  • Table per hierarchy
  • Type per hierarchy
  • Table per concrete Type

In this article we will understand Table per Hierarchy. We know that inheritance is nothing but a hierarchical concept, where one class is derived from another class. It forms a tree structure by classes and subclasses. The table per hierarchy concept says that, one table will get create per hierarchy. For example, if there is class A, and class B is derived from class A, then for that hierarchy only one table will get created in the database. So the basic concept is for a single hierarchy there will be one table. Have a look at the below code.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace CodeFirst
{
    public class Person
    {
        [Key]
        public int PersonId { get; set; }
        [Required]
        [MaxLength(10)]
        public string Name { get; set; }
        public string surname { get; set; }
    }

    public enum FriendType
    {
        Close,
        NotClose,
        FamilyFriend
    }

    public class Friend : Person
    {
        public Int32 Person { get; set; }
        public FriendType FriendType { get; set; }
    }


    public class TestContext : DbContext
    {
        public TestContext()
            : base("DBConnectionString")
        {

        }
        public DbSet<Person> Person { get; set; }
    }

}

In this example, we have implemented one hierarchy by inheriting the Person class within the Friend class. Entity Framework is smart enough to implement Table per Hierarchy without any external instructions.

Now let's have a look at the TestContext class. We are passing the connection string through the constructor and the connection string needs to be configured in the web.config file. Within the class, we are initiating only the Person class, not the Friend class. This is the beauty of Entity Framework. If we populate the base class then the related derive class will also automatically configure in a single table. Here is the connection string in the web.config file for this example.

  <connectionStrings>
    <add name="DBConnectionString"
    connectionString="Data Source=SERVERNAME;Initial Catalog=PersonDB;Integrated Security=true"
    providerName="System.Data.SqlClient"/>
  </connectionStrings>

Once we run the application, we will see that the database is created and table has generated as shown below.

If we closely look on table stricture we will see one Discriminator column. Why was the extra column created? We did not implement it in the code. Entity Framework has smartly created that field to distinguish between tables. The concept is like this: both the Person object and the Friend object will save in a single table, so how we will distinguish them? How will we know whether the particular row containing data is for the Person object or the Friend object. To distinguish between them, the Discriminator column has introduced. Here is the code where we are saving the object of Person class:

		static void Main(string[] args)
        {
            using (var ctx = new TestContext())
            {
                //Save Object of Person table.
                ctx.Person.Add(new Person { Name = "Sourav", surname = "Kayal" });
                ctx.SaveChanges();
            }
        }

Have a look on table data, we are seeing that "Person" has saved in Discriminator column value, so the record contains object of the Person class.

Now, we will save the object of the Friend class in the same table. Have a look at the below code:

static void Main(string[] args)
        {
            using (var ctx = new TestContext())
            {
                //Save Object of Person table.
                ctx.Person.Add(new Friend { Name = "Foo", surname = "Bar" ,PersonId = 1,FriendType =FriendType.Close});
                ctx.SaveChanges();
            }
        }

Here the data was saved in the table and the value for the Discriminator column is Friend.

Customize the "Discriminator" column

You may wonder: is it possible to change the default "Discriminator" column name? Or change it’s value? Yes, it’s possible. Using Fluent API we can do it. Have a look at the modified code.

public class TestContext : DbContext
    {
        public TestContext()
            : base("DBConnectionString")
        {
        }
        public DbSet<Person> Person { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Person>()
                        .Map<Friend>(m => m.Requires("ObjectType").HasValue("FriendType"));

            modelBuilder.Entity<Person>()
                        .Map<Person>(m => m.Requires("ObjectType").HasValue("PersonType"));
        }

    }

Now, when we will save the data of some Object. For example, the Friend Object will save the value "Friend Type," unlike "Friend" in the previous example. Let’s try to save data using the code shown below.

 static void Main(string[] args)
        {
            using (var ctx = new TestContext())
            {
                ctx.Person.Add(new Friend { Name = "Foo", surname = "Bar" ,PersonId = 1,FriendType =FriendType.Close});
                ctx.SaveChanges();
            }
        }

Have a look at the database structure. We are seeing that "FriendType" has saved in table because we have save object of Friend class.

Now, we will try to save the object of Person class in a table. Here is sample code:

static void Main(string[] args)
{
            using (var ctx = new TestContext())
            {
                ctx.Person.Add(new Person { Name = "Ram", surname = "Kumar" });
                ctx.SaveChanges();
            }
}

Now, the value is "Person Type" in table.

So we have learned the concept of table creation and the concept of the Discriminator column, now we will learn to fetch data from the table. To fetch data from such a table, we can use both a polymorphic and a non-polymorphic query. Just try both of them:

Polymorphic – Query

As the concept, it will pull all related hierarchical data in single query. Here we are pulling all data related to the Person Object. Now since Friend is derived from Person, Friend's information is pulling automatically. Here is the sample code.

			using (var ctx = new TestContext())
            {
                var data = from tab in ctx.Person select tab;
                List<Person> persons= data.ToList();
            }

See that both rowse have been fetched from the table so we are getting both the Friend and Person object.

Non-Polymorphic Query

In this query we will pull a particular column value. Here we are pulling the "Friend" object only.

	using (var ctx = new TestContext())
       {
                //Get All Friend From Person Table
                var data = from tab in ctx.Person.OfType<Friend>() select tab;
                List<Friend> persons = data.ToList();

       }

And we are getting only a single object.

Border line

We have learned to implement the Table per Hierarchy concept to implement inheritance in Entity Framework. Hopefully this article will help you to go ahead one step towards Entity Framework learning. In the coming articles we will understand the two additional inheritance strategies in the Entity Framework. environment.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sourav Kayal
Software Developer TIMKEN India research Institute
India India
I am software developer from INDIA, working in manufacturing domain. Beside my day to day development work, i like to learn new technology and update myself. I am passionate blogger and author in various technical community including dotnetfunda.com , c-sharpcorner.com and codeproject. My area of interest is modern web technology in Microsoft stack.
Follow on   LinkedIn

Comments and Discussions

 
GeneralMy vote of 5 PinprofessionalPragmateek25-Jul-14 8:49 
GeneralMy vote of 5 PinprofessionalCatchExAs12-Jul-14 7:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141220.1 | Last Updated 11 Jul 2014
Article Copyright 2014 by Sourav Kayal
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid