Sunday, July 6, 2014

Inheritance in Entity Framework: Table per Hierarchy

In this article we will learn to tackle inheritance in Entity Framework. If still you are not clear with the aim of the article, below few limes is for you.
We know that inheritance is a beautiful concept in Object Oriented programming and it gives the concept of re-usability, which is one of the important practices of software design principal. Ok, we will implement inheritance in class level, that’s fine but how it will implement in DB level?  As rule, we know derive class contains all property of base class, so is derive class table will contains all property of base class table?


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

·         Table per hierarchy
·         Table per type
·         Table per concrete class


In this article we will understand Table per Hierarchy. We know that inheritance is nothing but hierarchical concept, where one class is derived from another class.  It forms a tree stricture by classes and subclasses.  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 create in database.
So, the basic concept is for a single hierarchy, there will be one table. Have a look on 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 Person class within Friend class. Entity Framework is smart enough to implement Table per hierarchy without any external instruction.
Now, have  a look on TestContext class, we are passing connection string through constructor , the connection string need to configure in web.config file.
Within the class, we are initiating only Person class not Friend class, this is the beauty of Entity Framework, If we populate base class, then automatically the related derive class will also configure in single table.

Here is the connection string in 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 like below.

Now, if we closely look on table stricture, we will see one Discriminator column , why the extra column created ? We did not implement it in code.
Entity Framework has smartly created that field to distinguish between tables. The concept is like this, both Person object and Friend object will get save in single table, how we will distinguish them? How we will know whether the particular row containing data for Person object or Friend object.  Tow distinguish between them, the Discriminator column has introduced.
Here is the code where we are saving 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 objet of Person class.


Now, we will save object of Friend class in same table, have a look on 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 has saved in table and the value for Discriminator column is Friend.

Customize the “Discriminator” column
You may think that , 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 on 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 data of some Object , for example Friend Object, it will save value “Friend Type” unlike “Friend” in previous example. Let’s try to save data using below code.

        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 on 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 object of Person class in 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.


Fine, we have learned the concept of table creation and concept of Discriminator column, now we will learn to fetch data from the table.
To fetch data from such table, we can use both polymorphic and non-polymorphic query. Just have 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 Person Object, now, as Friend is derived from Person, so Friend information too pulling automatically. Here is sample code.

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

Just look that both two rose has fetched from table, so, we are getting both Friend and Person object.


Non-Polymorphic Query
In this query we will pull particular column value, here are pulling “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 single object. 


Border line:
We have learned to implement Table per Hierarchy concept to implement inheritance in Entity Framework, hope this article will help you to go ahead one step towards Entity Framework learning. In coming article we will understand two more inheritance strategy in Entity Framework environment.

3 comments: