Search code examples
c#entity-frameworkmaxlengthdiscriminatortph

How to customize name, length and value of a discriminator column with Entity Framework 6


I try to use EF6 with an existing database I must be compatible with. The database has been generated by nHibernate and some tables use the table-per-hierarchy (TPH) inheritance model.

Discriminator columns are named Category (instead of Discriminator) and have an SQL length of 255 (instead of 128). Values are also different from what EF would generate.

How can I configure EF to use the existing columns (name, size and values)?

I tried to define a custom convention:

protected class DiscriminatorRenamingConvention : IStoreModelConvention<EdmProperty>
{
    public void Apply(EdmProperty property, DbModel model)
    {
        if (property.Name == "Discriminator")
        {
            property.Name = "Category";
            property.MaxLength = 255;
        }
    }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntityA>().Map(x => x.Requires("Category").HasValue("CatA"));
    modelBuilder.Entity<MyEntityB>().Map(x => x.Requires("Category").HasValue("CatB"));
    modelBuilder.Conventions.Add<DiscriminatorRenamingConvention>();
    base.OnModelCreating(modelBuilder);
}

This generates a column named Category but with a length of 128, whatever the order of instructions in the OnModelCreating method. Specifying category values seems to overwrite MaxLength.


Solution

  • Here

    modelBuilder.Entity<MyEntityA>().Map(x => x.Requires("Category").HasValue("CatA"));
    

    you specify the name of the discriminator to be "Category", so this

    if (property.Name == "Discriminator")
    

    will evaluate to false, hence the MaxLength will be the EF default.

    To get the desired behavior, use Requires("Discriminator") and let the convention do the rest.