How does EF tell apart TPC and TPT inheritance models? - entity-framework

For Table Per Concrete Type model the whole entity is stored as a row in one table.
For Table Per Type additional tables contan only specific to descendant type data.
If the forst case EF issues one insert, and in the second one it must issue two inserts: for base and for inherited types' tables.
I cannot understand how EF knows what to do. The only difference I see now is just mappings in MSL: either they overlap or not.

Related

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?
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.

model first table per concrete type (TPC) inheritance saves to both tables

trying to implement table per concrete type using model first, but when saving the derived type, EF saves to both the base and derived tables. how do you configure EF to save the type to the correct corresponding table?
There is a good discussion of choosing an approach here that recommends against TPC for Entity Framework: http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx
For this reason: While the EF runtime supports TPC, the designer doesn't, and using TPC in the EF forces you to avoid associations in your base type. Because of these issues we generally discourage the use of TPC with the Entity Framework.
My best guess is that if you are writing to a base and derived tables as your problem you have tried to implement this where you have a concrete class which is extended by an additional concrete class? As per the discussion above, the simple answer is TPC will not work like this for EF (the referenced article is 2009, but I don't think this has changed).

Setting up relation to base model which has many classes that inheritate in Code First Entity Framework

I'm creating my db using code-first and entity framework. I'm defining all my models which works great, but now I have a Page class which can contain Blocks.
These Blocks have a base class with ID, BlockType, Position, Name etcetera but there are different types of blocks with different properties which are classes that inherit from this base class. I'm wondering how I can setup my models so the page can have a collection of 'blocks' without storing the custom properties in a comma seperated list or something like that.
Is it possible? And what is the 'good' way to model this..
Thanks in advance!
Entity Framework supports inheritance. There are various strategies to map your object model - base and derived classes - to a database schema. The most important are:
Table per hierarchy (TPH): Base class and all derived classes will be mapped to a single table in the database. Any custom properties of derived classes will appear as separate columns in the table and the table contains a discriminator column to distinguish between the types. EF manages to load the columns needed to materialize a specific type.
Table per type (TPT): The base class has its own table which only contains the base class properties. Every derived entity gets another table that has the additional properties of this type. EF manages to load the properties from the different tables (creating appropriate joins) that contain all properties to materialize a specific type.
TPT is - in my opinion - the cleaner approach to implement inheritance, but it currently (EF <= 4.3) has performance problems compared to TPH due to suboptimal SQL generated by EF. The problem will be solved in EF 5.0. But TPH will still remain the more performant way of mapping because it doesn't need to join multiple tables.
Benefits and drawbacks of the strategies are discussed in detail in the linked blog posts. In the blog you can also find the third (less often used) option - Table per concrete type (TPC).

One Entity for multiple similar tables

have two tables in database.
They have completely the same columns, only the difference between them - they have different names.
Lets say i have TableSea with column s Id and Name and TableOcean with the same columns Id and Name.
I want to use EF 4 to be able CRUD operations, i am also want to use stored procs mapping for insert update and delete operations.
I am already created POCO entity for first table and i did create stored procedures and map them to entity model. All working well.
How make it work with two tables without create a new entity for second table?
AFAIK, you can't, and you definitely shouldn't!
If you have two identical database tables, then this means one of the following:
The two tables mirror closely
related concepts (like Sea and Ocean
in your example).
The two tables
mirror different concepts which only
accidentally have the same
properties.
Depending on which scenario is closer to reality, you have these two design options:
Merge the two tables and add a
Type property (column), then map
it to one entity type. You might
have different subclasses to
differentiate between types, or you
may go with an additional Type
property - whichever fits better for
you.
Have two tables. Which means: there are two different concepts. Consequently, this has to be mirrored by two different entities in the business model.
In any case, having an entity table in the database means having an entity class in the business model. If there's no such 1:1 - mapping, then clearly something is wrong with the design!
Thomas

ADO.NET Entity Framework Hierarchy type Inheritance Error 3032 Workaround?

I would like to implement a Hierarchy Type Inheritance ... i.e. Cars to BMWs ... Cars would have CarTypeID that is associated with CarTypes. I would like CarTypeID to be the discriminator column. Unfortunately, I cannot do this in ADO.NET Entity Framework.
If I would like to keep the association, how am I able to achieve this?
Has anyone come up with a work around?
You can't do this. You must use a different column, as the column which is a constrained FK end and the inheritance discriminator column cannot be the same.
I'm of mixed minds as to whether this is a bad thing or not. I think inheritance is often overused, especially in O/R modeling. If you already have a FK to car type info...