Code First Entity Framework - Table Per Concrete Class

1. Classes in .Net can be inherited and extended, with new properties added for the sub classes. Entity Framework allows you to represent this in three main ways: Table-Per-Type, Table-Per-Hierarchy, Table-Per-ConcreteClass. This article describes Table-Per-ConcreteClass.
2. In Table-Per-ConcreteClass, every instance of a class derived from the base class gets its own table, but the properties from the base class are duplicated in each table. There is no table to represent the base class, only concrete classes get an implmentation. Let's see how that works. As before we have our Animal class (this time abstract so we can't instantiate it) and our two derived classes Dog and Cat:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;

    public abstract class Animal
    {
        [Key]
        [Required]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Required]
        public bool WarmBlooded { get; set; }

        [Required]
        [StringLength(100)]
        public string NotedCountry { get; set; }
    }

    public class Dog : Animal
    {
        [Required]
        [StringLength(100)]
        public string Name { get; set; }

        [Required]
        [StringLength(100)]
        public string Colour { get; set; }
    }

    public class Cat : Animal
    {
        [Required]
        [StringLength(100)]
        public string Breed { get; set; }

        [Required]
        [StringLength(100)]
        public string FavouriteFood { get; set; }
    }

3. Now we create a context for it, as before, but this time we need to tell EF how we map our objects to two new tables:

using System.Data;
using System.Data.Entity;
using System.Data.EntityModel;

public class AnimalContext : DbContext
{
    public DbSet<TestEF.Entity.Animal> Animals { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Entity.Dog>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Dogs");
        });

        modelBuilder.Entity<Entity.Cat>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("Cats");
        });
    }
}
The MapInheritedProperties tells EF to copy all the properties from the base class and create them in this class, and the ToTable directs EF to save the mapped object in a new table.

4. Add a table generation plan line in Application_Start in Global.asax as before:
    Database.SetInitializer<TestEF.Contexts.AnimalContext>(new DropCreateDatabaseAlways<TestEF.Contexts.AnimalContext>());
And a connection string line in web.config
    <add name="AnimalContext"
         connectionString="Persist Security Info=False;Initial Catalog=MySchoolDB;Server=MYSERVER/Instance;Connect Timeout=30"
         providerName="System.Data.SqlClient"  />
5. Now we can create a Dog and a Cat in our code behind or MVC controller:

    using (TestEF.Contexts.AnimalContext AnimalKingdom = new TestEF.Contexts.AnimalContext())
    {
        Entity.Dog doggy = new Entity.Dog();
        doggy.NotedCountry = "England";
        doggy.WarmBlooded = true;
        doggy.Name = "Fido";
        doggy.Colour = "Brown";

        Entity.Cat pussy = new Entity.Cat();
        pussy.NotedCountry = "Ethiopia";
        pussy.WarmBlooded = true;
        pussy.Breed = "Abyssinian";
        pussy.FavouriteFood = "Fish";

        AnimalKingdom.Animals.Add(doggy);
        AnimalKingdom.Animals.Add(pussy);

        AnimalKingdom.SaveChanges();
    }
When we run this, we get an error. The error complains about a unique constraint on the entities. What's going on?

If you think about it, the answer is obvious. Whereas in the Table-Per-Type style of implmentation, the unique key of the 'animal' was controlled by the Animal table, because Animal has no database implementation (since it is not a concrete class) then the two sub-tables try to implement an identiy key on their own. So the Cat line gets id=1, and the Dog line gets id=1. Unfortunately, since they are both types of Animal, and the Id field rightly belongs to that class, Entity Framework now has two Animals with the same primary key - which can't happen, thus the error.
5. In order to make this work, WE MUST PROVIDE THE PRIMARY KEYS and make sure they are unique:

    using (TestEF.Contexts.AnimalContext AnimalKingdom = new TestEF.Contexts.AnimalContext())
    {
        Entity.Dog doggy = new Entity.Dog();
        doggy.NotedCountry = "England";
        doggy.WarmBlooded = true;
        doggy.Name = "Fido";
        doggy.Colour = "Brown";
        doggy.Id = 1; // yuk!

        Entity.Cat pussy = new Entity.Cat();
        pussy.NotedCountry = "Ethiopia";
        pussy.WarmBlooded = true;
        pussy.Breed = "Abyssinian";
        pussy.FavouriteFood = "Fish";
        pussy.Id = 2; // double yuk!

        AnimalKingdom.Animals.Add(doggy);
        AnimalKingdom.Animals.Add(pussy);

        AnimalKingdom.SaveChanges();
    }
This is by far the most annoying aspect of TPC design, and probably explains why it's not used much. We could get around this by making the PK fields of the sub-tables GUID types, and just generate new unique GUIDs each time, but this is messy, and makes sorting and searching horrible. We could have a separate table providing incremental unique integers shared between the types, but then we're back to TPT again with a table for the base class.

My advice is... don't use it!
And that's the basics of Table-Per-ConcreteClass class representation in Entity Framework.