views:

35

answers:

1

Hi everyone,

I am trying to resolve a situation I ran into when implementing EF with my project.

I have absolved the table-per-type approach, in my case the ActionUpdate derives from the ActionHistory and that works fine.

What I am trying to achieve is to derive the ActionUpdate from the ActionHistory, and to have a navigation property at the ActionUpdate which will hold a collection of ActionUpdateDetail entities.

The problem starts with the inheritance: when I delete the ActionHistoryId from ActionUpdate, as per the MSDN sample, and then derive from ActionHistory and do the re-mapping, the ActionUpdateId automatically turns into non-PK property.

That behavior prevents me from mapping to the ActionUpdateDetail entity, as my new derived class does not contain the PK anymore :( I should map ActionUpdate.ActionUpdateId to ActionUpdateDetail.ActionUpdateid

My assumptions:

1) It is either not possible at all to achieve something like this, 2) I am just a stupid fart trying to do things the wrong way, 3) I am doomed :)

Any help with this issue is appreciated!

The picture depicts the entities I currently operate with.

The cause to the problem

I think it's important that I share with you the cause to my agony :)

I intuitively presumed that ActionUpdateDetail must map to ActionUpdate's Id, which was wrong.

Instead, it has to map to the ActionHistoryId property of ActionUpdate entity, because the ActionUpdate derives from the ActionHistory.

This little change caused the ActionUpdate table to lose it's Id column, i.e. it only contains the ActionHistoryId column. The reason for the existence of that single-column table is due to the fact that ActionHistory is an abstract entity, and I need something, i.e. ActionUpdate to hold the set of ActionUpdateDetail entities.

I hope this could help someone the same way I was helped :)

A: 

It is possible to use table-per-type inheritance with EF and using the example you provide i'll write a little drive-through. You just need to follow these steps:

  1. Go to the Entity Data Model (double click on *.edmx)
  2. Delete the association between ActionUpdate and ActionHistory
  3. Right click on ActionHistory, Add > Inheritance, Select ActionHistory as base class and ActionUpdate as derived class
  4. Delete the primary key of ActionUpdate(ActionUpdateID). It doesn't matter that it is not a PK no longer, because you are going to use the base class PK. From the model's point of view, your ActionUpdates will be a subset of ActionUpdateID
  5. Open the Map Details window, select ActionHistory and map the id from the database with the field ActionHistoryID. From now on, this entity will use its base class primary key.
  6. Compile or Validate the model and it should work
  7. If you have any problem with the ActionUpdateDetails associated with ActionUpdates (you shouldn't but you never know with EF) you can check the association constraints (select association > properties panel)

Important Note: To make a table-per-type inheritance the base and derived classes must establish a 1 to 0..1 relationship. So your model wouldn't support this type on inheritance. Why do you want to derived the ActionUpdate entity from the ActionHistory entity?

Vintharas
Hi Vintharas, first I wish to thank you for your detailed and quick reply :) ActionHistory is an abstract class. There also other tables / entities such as ActionTransferToDepartment or ActionTransferToUser. The specific action is the update one because it should map to the set of updated fields. Hence, ActionUpdate maps 1 to 1 with ActionHistory, and it maps 1 to many with the ActionUpdateDetail. I will try to do as you suggested, however I am confused about the step No. 5, shouldn't the ActionHistory's Id be already mapped?
bignermo
A pleasure! If ActionHistory is an abstract class then you should mark it in the model with the Abstract property set to true. About Step Number 5: Normally, the ActionUpdateID property of the entity will be mapped to the column ActionUpdateID on the database, as you delete that property from your model (in step 4) that mapping will be unresolved. That's why you have to kick in and set it to the ActionHistoryID which the entity inherits from its base class.
Vintharas
You have to be aware also that in EF4, ActionUpdate will work as a subset of ActionHistory so whenever you want to make a query you have to use something like this: var query = ctx.ActionHistory.OfType<ActionUpdate>();
Vintharas
Great tips, thanks!
bignermo