EF6 Table-per-Hierarchy (TPH) - abstract base class with abstract property does not generate a migration

593 views Asked by At

I have an abstract base class set up for TPH:

public abstract class BaseSchema
{
    ...
    public abstract bool IsFilterRequired { get; set; }
    ...
}

.. and I inherit from it in other derived classes as per:

public class DerivedSchema : BaseSchema
{
    .....
    public override bool IsFilterRequired{ get; set; }
    ....
}

This setup works fine for the other inherited properties in these classes (those i have left out) and this is working to date.

It's the addition of the 'IsFilterRequired' property that i've shown above that's the issue - I'm adding this abstract property to the base class and overriding it in the derived class. I would expect that EF would pick this up and generate a migration to add the new column to the SQL Server table, but it just creates an empty migration.... What could be wrong with this? Thanks!

1

There are 1 answers

0
Ciaran On BEST ANSWER

Thanks to @ivan-stoev for the direction. Basically, abstract properties are ignored by EF. If you wish to specify a property on your base class to be inherited by derived classes, you will want EF to create a database column to represent this. Marking the property as 'virtual' allows EF to create the column:

public abstract class BaseSchema
{
    ...
    public virtual bool IsFilterRequired { get; set; }
    ...
}

As an aside, if you have multiple derived classes inheriting from the common TPH base, this property will now be available to all of them. If this is behavior you don't want, you'll need to override it in the derived classes it doesn't belong to and mark it as not implemented. Not ideal, but better than the alternative and it'll throw a very easy to catch runtime error that'll get caught in Unit Testing.

public class DerivedSchemaThatDoesNotNeedThisProperty : BaseSchema
{
...
    public override bool IsFilterRequired
    {
        get { return false; }
        set { throw new NotImplementedException($"{nameof(IsFilterRequired)} property is not implemented in this class."); }
    }
... 
}