Hi Guys,
I have an EF4 Model that is built with abstract entities/classes:
Notice how State entity has a navigational property called Country.
Note: I have lazy-loading disabled, so i must eager-load on demand.
Now, if i have the following method:
public Location FindSingle(int id)
{
return _repository.Find().WithId(id).SingleOrDefault();
}
This does not return any associations by default. But how can i dynamically eager-load the associations when i explicitly want to?
I cannot do this:
return _repository.Find().WithId(id).Include("Country").SingleOrDefault();
As i am working with an abstract class called Location, which does not have a navigational property called "Country". I do not know what the derived type is until i actually execute the query with .SingleOrDefault
.
So, here's what i've had to do:
public Location FindSingle(int id, bool includeAssociations = false)
{
var location = _repository.Find().WithId(id).SingleOrDefault();
return includeAssociations
? LoadAssociation(location)
: location;
}
private Location LoadAssociation(Location location)
{
// test derived-type, e.g:
var state = location as State;
if (state != null)
return _repository.Find().OfType<State>().Include("Country").WithId(id).SingleOrDefault();
}
Essentially, i'm doing 2 identical calls. Does it work? Yes. Is it pretty? No, and it's not really "eager-loading".
I know this is not the correct solution, can you guys think of the proper one? (and yes i know i can use stored procedures, but i really want to go through my repository/model here, so the entities are correctly attached to the graph, ready for editing).
Even though .Include
causes a Left Outer Join, the problem is i'm working off the "Locations" entity set. I need to .Include
on the "State", but "States" belong to the "Locations" entity set (derived classes belong to their parent's entity set).
So i guess my question is actually pretty generic - how do we do a .Include on a child of an abstract entity, when we don't know what the child is beforehand?
Remember, i cannot use .OfType<T>()
first (and then the .Include on the derived type), as i don't know what T is (and neither does the calling code), hence generics cannot be utilized here.