As I understand it, Table Per Hierarchy is the default (?) in asp.net mvc code first. Yet when I create an abstract base class and two empty sub classes, the migration wants to create two separate tables instead if one table with a discriminator column.
public abstract class ShippingBase : Entity
{
public ShippingBase()
{ }
public bool IsDefault { get; set; }
}
public class Shipping : ShippingBase
{
public Shipping():base()
{ }
}
public class FlatRateShipping : ShippingBase
{
public FlatRateShipping():base()
{ }
}
I add the two sub classes to the db context:
public virtual IDbSet<Localization.Shipping> Shippings { get; set; }
public virtual IDbSet<Localization.FlatRateShipping> FlatRateShippings { get; set; }
And I do not do anything in OnModelCreating.
I am using ASP.NET Boilerplate, but as far as I know it does not change any setting that would give this result. I know how to force TPC, but since TPH is default I have not found any way to set it. Is there any way to force TPH instead? Or am I missing something with my classes?
This is the resulting migration:
public override void Up()
{
CreateTable(
"dbo.FlatRateShippings",
c => new
{
Id = c.Int(nullable: false, identity: true),
IsDefault = c.Boolean(nullable: false),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Shippings",
c => new
{
Id = c.Int(nullable: false, identity: true),
IsDefault = c.Boolean(nullable: false),
})
.PrimaryKey(t => t.Id);
}
That's because they inherit from an abstract class. Abstract classes are ineligible to be mapped to tables, because they can never be instantiated on they're own. You can have an abstract class in the inheritance chain, but only the first concrete class that derives from it will get a table. For example, if you make FlatRateShipping
inherit from Shipping
, then the data for both will end up in dbo.Shippings
(default pluralization).
If it doesn't make sense to have FlatRateShipping
inherit from Shipping
(because they're logically siblings, rather than parent-child), then really Shipping
is too generic of a name. Rename it to something more descriptive on what it actually is about, and then make Shipping
simply a concrete implementation of ShippingBase
that both can inherit from.
If none of that is to your liking, you can simply make ShippingBase
not abstract and achieve the same result (though your table will be dbo.ShippingBases
by default).