The official approach to defining navigation properties for complex entities is:
public class SuperEntity
{
public int Id { get; set; }
//Other properties
}
public class LowerEntity
{
public int Id { get; set; }
public int SuperEntityId { get; set; }
public virtual SuperEntity SuperEntity { get; set; }
//Other properties
}
The main thing here is that a class that references (allows navigation to linked super entity) has both public SuperEntity SuperEntity { get; set; } property, as well as it’s Id in public int SuperEntityId { get; set; }.
I have gone a few days into my entities design ommiting the public int SuperEntityId { get; set; } property in the “lower entities”. So I am navigating only by virtual SuperEntity property. And everything works fine! But I had people on SO telling me that it creates an excessive tables in the DB. I’ve checked, and that is not true. When I use my approach, the DB tables has the SuperEntityId column and just populates it with the referenced entity Id automatically. What’s the point in this public int SuperEntityId { get; set; } field then?
Or, perhaps, what I am doing became available in a “fresh” versions of EF like 4.3?
The point of SuperEntityId is that it is sometimes easier to use a foreign key property in apps where your context isn’t alive the entire time, e.g. a webapp.
In such a situation, it’s a lot easier to just use a foreign key property, than to try to attach object B to object A.
As far as I know, with nav properties, EF uses an object to track the relation between 2 objects. So if you want to couple object B to object A, in a disconnected app, it’s not enough to just set the property on object A, you also have to fiddle with the entry of object A in the changetracker to register the relation between B and A.
Setting a foreign key property is the equivalent of this fiddling.
When we were just beginning with EF and didn’t know about all of this, every time we wanted to connect 2 objects, e.g. B to A, and B already existed in the DB, the context thought that B was a new object instead of an existing one, and duplicated the record in the DB.