5

I have an Entity Framework Model created using Entity Framework Code First that is using Table Per Hierarchy inheritance where the structure looks a little like this:

public abstract class BaseState 
{
    public int Id { get; set; }

    public string StateName { get; set; }

    // etcetera
}


public class CreatedState : BaseState
{
    public User Owner { get; set; }

}

public class UpdatedState : BaseState
{
    public User Owner { get; set; }
}

Now what that creates is in my BaseStates table I have Owner_Id and Owner_Id1 stored. But given that no class will ever be both a CreatedState and an UpdatedState it seems as though it would be logical to use a single Owner_Id for both. Which would also make it easier to follow the database.

My basic question is: Is this possible with Code First EF4?

I have tried to map the columns:

public class CreatedState : BaseState
{
    [Column("OwnerId")]
    public User Owner { get; set; }

}

public class UpdatedState : BaseState
{
    [Column("OwnerId")]
    public User Owner { get; set; }
}

That appeared to have no effect.

Then I tried creating a shared parent class, which is probably more correct OO anyway:

public abstract class OwnedState : BaseState
{
     public User Owner { get; set; }
}


public class CreatedState : OwnedState
{

}

public class UpdatedState : OwnedState
{

}

Again, no dice. Or, more worryingly, this appears to work in some cases and not in others ( obviously my real configuration is slightly more complex ) when I can see precisely no difference between the classes where it does work.

Edit for more detail on what fails: I have two fields that behave in the way I have described above, we might call the associated classes OwnedState and ActivityState, both of which I have created as an abstract class in the way shown in my last example. OwnedState has two classes that derive from it, ActivityState has three. In the database I have ActivityState_Id but also OwnedState_Id and OwnedState_Id1.

I can see no difference at all between the OwnedState and ActivityState classes aside from the type that they reference ( both other entities ) and yet in the database it appears as though EF has somehow interpreted them differently- I don't understand the EF internals well enough to know how it makes that decision.

glenatron
  • 11,018
  • 13
  • 64
  • 112
  • I suppose you can't use a static field, since not all child classes share the same value? – John Willemse Apr 19 '13 at 11:38
  • @JohnWillemse correct. I don't know how well Entity Framework Code First POCOs ( when did I become the kind of programmer who had to type phrases like that? ) play with static fields. – glenatron Apr 19 '13 at 12:15
  • Putting into the base class like you did should work actually - you need to be more specific what `doesn't work` if it doesn't. – NSGaga-mostly-inactive Apr 19 '13 at 12:25
  • And your `[Column("OwnerId")]` doesn't have any effect - if you want something like that put the `public int OwnerId { get; set; }` fk alongside the navigation. But is irrelevant in your case. – NSGaga-mostly-inactive Apr 19 '13 at 12:28
  • @NSGaga updated the question- basically I use the same technique twice in seemingly identical ways but it only works in one case. – glenatron Apr 19 '13 at 15:21

1 Answers1

0

If you want to have one Owner_ID to have both CreatedState and UpdatedState to refer to, then the User Owner should be placed in the BaseState.

I don't know what you are trying to do with this, but logically, you wouldn't be having CreatedState and UpdatedState as classes, but more of values of State property (or column in database) to save the state (Created or Updated). But, again, maybe you are trying something else with this.. I guess.

workaholic
  • 31
  • 3
  • If they aren't classes what is the state? Is it just an arbitrary string? As you can see from the last code block in the question, I tried having the property on a parent class and Entity Framework was still doing the same weird thing with it. The question was really about why EF was being weird and creating extra fields rather than whether the intent of the simplified design I created for the question was practical, which it isn't. – glenatron Jan 14 '15 at 09:23
  • @glenatron Having separate class for the states will still not give you the state to be stored. My advise on the above question would be to create enum for state such as enum State {Created, Updated} and then store that in a class as a property. This will also allow you to store one of Created and Updated state values which handles the case when two states can both be stored. (as it does not make sense to have the state Created and Updated at the same time.) – workaholic Jan 15 '15 at 03:23
  • @glenatron Please understand that I was just trying to identify the purpose of the OwnerId being in the State class rather than the BaseState class so I can help. – workaholic Jan 15 '15 at 03:24
  • There was no way to use Enums with Entity Framework prior to version 5, which wasn't usable for the project this question was about- it's a few years back now. Also each state had a set of other information associated with it, many of them in common but some of them different depending on which state it was. It's a fairly standard scenario for using inheritance if one wasn't dealing with weird ORM behaviour. – glenatron Jan 15 '15 at 09:37
  • Although the Enum was not supported with EF, it can be converted either to String or Int which allows EF to use as a column. But I think this is off the topic as you want to use inheritance. – workaholic Jan 16 '15 at 00:32
  • @glenatron It is not a weird behavior that two different properties (with the same name though) were converted to separate columns. There is no way that the EF to identify it was intended to share the same column for a property located in two different classes. That's why I recommended to define the Owner property in the base class, so one column for Owner property be created for both CreatedState and UpdatedState. – workaholic Jan 16 '15 at 00:36
  • the last section of the question shows how even when the Owner property was _on_ the base class, it still created two properties. That was the behaviour I considered weird. – glenatron Jan 16 '15 at 09:53