EF Feature CTP5: Inheritance Scenarios with Code First Fluent API

December 12, 2010

EF Feature CTP5: Inheritance Scenarios with Code First Fluent API

One of the interesting features of Code First fluent API is the ability EF Feature CTP5: Inheritance Scenarios with Code First Fluent APIto configure inheritance in your model. Since one of the strengths of an O/RM solution is its ability to map inheritance then this feature is a must in every mapping scenario (may it be Model first, Database First or Code First). In this post I’ll show how to configure inheritance by using the fluent API.

Revisiting Entity Framework Inheritance Types

In the past I wrote a series of posts about inheritance mapping in Entity Framework which you can read here:

Configure Inheritance Using Code First Fluent API

In the previous CTPs in order to create inheritance we had to use the MapHierarchy method which was very tedious. In this version the MapHierarchy method was replaced by the Map method (and not in all the inheritance mapping scenarios you’ll need to use it). Lets explore the inheritance types:

Table per type (TPT) inheritance
In order to create this type of mapping all you have to do is to use the ToTable method:

public class Course
{
  #region Properties
 
  public int CourseID { get; set; }
  public string Title { get; set; }
  public string Days { get; set; }
  public DateTime Time { get; set; }
  public string Location { get; set; }
  public int Credits { get; set; }    
 
  #endregion
}
 
public class OnLineCourse : Course
{
  #region Properties
 
  public string CourseURL { get; set; }
 
  #endregion
}
 
public class SchoolEntities : DbContext
{
  #region Properties
 
  public DbSet<Course> Courses { get; set; }
 
  #endregion
 
  #region Methods
 
  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
    modelBuilder.Entity<Course>()
      .ToTable("Courses");
 
    modelBuilder.Entity<OnLineCourse>()
     .ToTable("OnLineCourses");
  }
 
  #endregion
}

You start with creating the inheritance in the model itself (OnLineCourse inherit from Course) and then in the DbContext’s OnModelCreating method you specify that every type will be mapped to its own table using the ToTable method.

Table per hierarchy (TPH) inheritance

In order to create this type of mapping you need to use the Map method. In the lambda the Map method gets you write the discriminator field and its values using the Requires and HasValue methods. In the following example you can see how to do exactly that:

public class Course
{
  #region Properties
 
  public int CourseID { get; set; }
  public string Title { get; set; }
  public string Days { get; set; }
  public DateTime Time { get; set; }
  public string Location { get; set; }
  public int Credits { get; set; }    
 
  #endregion
}
 
public class OnLineCourse : Course
{
  #region Properties
 
  public string CourseURL { get; set; }
 
  #endregion
}
 
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<Course>()
    .Map(c =>
    {
      c.Requires("Discriminator").HasValue(1);
    })
    .Map<OnLineCourse>(olc =>
    {
      olc.Requires("Discriminator").HasValue(2);
    });
}

Table per concrete type (TPC) inheritance

In order to create this type of mapping you will start as it is a table per type inheritance configuration. The only change is the use of the Map method on the concrete type. In the method lambda you will use the MapInheritedProperties method to indicate it is a concrete type:

public class Course
{
  #region Properties
 
  public int CourseID { get; set; }
  public string Title { get; set; }
  public string Days { get; set; }
  public DateTime Time { get; set; }
  public string Location { get; set; }
  public int Credits { get; set; }    
 
  #endregion
}
 
public class OnLineCourse : Course
{
  #region Properties
 
  public string CourseURL { get; set; }
 
  #endregion
}
 
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<Course>()
    .ToTable("Courses");
 
  modelBuilder.Entity<OnLineCourse>()
   .Map(olc =>
   {
     olc.MapInheritedProperties();
   }).ToTable("OnLineCourses");
}

Here is a simple check to see how the database is created in each inheritance type:

using (SchoolEntities context = new SchoolEntities())
{
  context.Database.Delete();
  var course = new Course
  {          
    Credits = 2,
    Days = "MF",
    Location = "Class 1",
    Time = DateTime.Now,
    Title = "Entity Framework",
  };
  var onLineCourse = new OnLineCourse
  {          
    Credits = 3,
    Days = "WT",
    Location = "Class 2",
    Time = DateTime.Now,
    Title = "Entity Framework On Line",
    CourseURL = "http://www.gilfink.net",
  };
  context.Courses.Add(course);
  context.Courses.Add(onLineCourse);
  context.SaveChanges();

Pay attention that in the TPC inheritance the database will be created properly and the insert will succeed but there will be an exception of overlapping keys (both courses will be created with CourseID of 1 and in the context there will be overlapping).

Summary

Using the Code First fluent API for inheritance is easy. In the post I showed how you can do that using the three main inheritance scenarios in Entity Framework.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

2 comments

  1. VladimirDecember 13, 2010 ב 21:30

    Thanks!
    Can you explain, what is “Discriminator” value? Is there missed property in model?

    Reply
  2. Gil FinkDecember 14, 2010 ב 14:19

    @Vladimir,
    The discriminator is a field in the database table that differentiate between the entities in Table Per Hierarchy inheritance. For each entity there will be a diffrent value in that field.

    Reply