'EF Core HasData Seeding a TPH Entity

I want to use the EF Core HasData method to seed a database with reference data. Two of the models I want to seed follow the Table per Hierarchy (TPH) pattern in the sense that there is a none abstract base type and another none abstract derived type. These models in the database exist in a table named after the base type with a discriminator column. I would like to add data seeding for this table. However I’m struggling to find any guidelines of how to do so in the EF Core 6 documentation.

I have a few related questions:

Do I seed all the data using the HasData method on an EntityTypeBuilder<BaseType> or do I need to split the seeding into one HasData on that class and another on EntityTypeBuilder<DerivedType>?

I understand using TPH will add a shadow discriminator property and that, potentially, I’ll have to add that in the data seeding. Does that mean I have to use anonymous types to specify that property (doesn’t seem very elegant) and if so, can I get the autogenerated discriminator name using a method (typing it manually sounds like a risk as what if EF Core changes the discriminator name convention?)?

Should I be avoiding using TPH on reference tables altogether? Is there something else I should do instead?



Solution 1:[1]

After going through my options with trial and error, I have come to the following solution. It may not be perfect, but it deals with all of my concerns.

Do I seed all the data using the HasData method on an EntityTypeBuilder<BaseType> or do I need to split the seeding into one HasData on that class and another on EntityTypeBuilder<DerivedType>?

You have to do it on both classes, attempting otherwise throws on creating the migration: The seed entity for entity type 'BaseType' cannot be added because the value provided is of a derived type 'DerivedType'. Add the derived seed entities to the corresponding entity type.

I understand using TPH will add a shadow discriminator property and that, potentially, I’ll have to add that in the data seeding. Does that mean I have to use anonymous types to specify that property (doesn’t seem very elegant) and if so, can I get the autogenerated discriminator name using a method (typing it manually sounds like a risk as what if EF Core changes the discriminator name convention?)?

I have added a property to the BaseType class and defined it as the discriminator, so now I can specify the discriminator values directly without using anonymous type and I am in control of the discriminator values. Gert Arnold points out in this other answer why this might not be appropriate. However I have used the following method described in this EF Core Github issue to hopefully mitigate the concerns he raised.

Should I be avoiding using TPH on reference tables altogether? Is there something else I should do instead?

This is still unanswered. But I am feeling a lot more confident it is a good approach now.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 CallumBateson