Inheritance and polymorphisme with entity framework

Inheritance

The entity framework code first lets you define you domain models first and generates based on that the necessary tables in the database. When you create you models you normally use inheritance to keep you code dry ( dont repeat yourself )  but how does the entity framework convert this to tables in your database. For this there are three strategy's:

Table per hierarchy (TPH)

This is the default strategy. Entity framework goes to your primairy type ( the base or abstract type ), creates a table for it. Detect all the inheritance and adds the property's off all the classes which inherits of this base class as fields to the created table. This has some advantages

  • An easy'er database scheme. Easy'er to read. Easy'er to maintain
  • Query performance is better, everything is stored in one table so no joins so better performance.

Disadvantage is:

  • Your data maybe not fulle denormalized at database level. Which can cause some problems wicht duplicate data in your application!

Table per type ( TPT )

For each type a table is created meaning that there is allso a table for the type the primairy type is inherited from. The advantage is disadvantage of the TPH strategy and vice versa.

  • Data is stored completely normalized in database.
  • Database scheme is harder to read because of the 'inherited' tables and there relationships.

Disadvantage is:

  • Slower query's because of the join to the 'inherited' table.

At this moment there is no property for choosing between inheritance mapping strategy. Default is a table per hierarchy but if you want to use a table per type you will have to override the onmodelcreated event and speficfy which table has to be created.

    public class Data : DbContext
    {
        // constructor
        public Data()
            : base("name=Data") {}

        // properties
        public virtual DbSet<Customer> Customers { get; set; }
        public virtual DbSet<Address&gt Addresses{ get; set; }

        // methods
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Person>().ToTable("Persons");
        }
    }

    [Table("Customers")]
    public class Customer
    {
        // propertys
        public int CustomerId { get; set; }
        public int KlantNumber { get; set; }

        // navigation
        public virtual ICollection<Address> Addresses { get; set; }

    }

    [Table("Persons")]
    public class Person
    {
        // propertys
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDay { get; set; }

    }

So here we defined that the entity framework has to create a table and the necessary relationships for the Person type.

Table per concrete type ( TPT )

Again this is a strategy and you have to implement it yourself. A table per concrete type means that you create a table foreach type wich is not an abstract class. Entity framework will now create tables for each non-abstract class and will add the property's of the inherited class as fields to this class. This is maybe the best of both worlds. Example:

    public class Data : DbContext
    {
        // constructor
        public Data()
            : base("name=Data") {}

        // properties
        public virtual DbSet<Customer> Customers { get; set; }
        public virtual DbSet<Address> Addresses{ get; set; }

        // methods
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Customer>().Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("Customers");
            });
        }
    }

    [Table("Customers")]
    public class Customer
    {
        // propertys
        public int CustomerId { get; set; }
        public int KlantNumber { get; set; }

        // navigation
        public virtual ICollection<Address> Addresses { get; set; }

    }

    [Table("Persons")]
    public class Person
    {
        // propertys
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDay { get; set; }

    }

{{opmerking.Naam}}:

{{opmerking.OpmerkingText}}

            

Saving your comment....

Naam is verplicht!
Email is verplicht!
Opmerking is verplicht!