
Question:
I'm hoping someone out in the SO community will be able to help me out here.
Simplified Background: I'm using Entity Framework V1 to build my class structure that is outlined below, I'm using Table Per Type to persist my inherited objects:
Employee
CaseA : Case
CaseB : Case
CaseC : Case
<em>CaseB has a Navigational Property to Employee</em>
I have a Repository that returns an ObjectQuery. If the type of Case is actually CaseB, I need to include the Employee object within the graph. I can't .Include("Employee") because it's not a navigational property of Case, and Employee doesn't have a .Load() method on it.
Ideally I want to be able to do this in one query, however as a fall back I'm happy that I make a call, check the Object and perform another call, something like this: (although as I stated earlier, load doesn't exist on the employee navigational property)
//Get the case from the
Case myCase = new Repo<Case, Entities>.FirstOrDefault();
if(myCase is CaseB)
((CaseB)myCase).Employees.load();
Am I missing something really simple here?
Answer1:Try this:
var employee = ctx.Cases
.OfType<CaseB>()
.Include("Employees")
.Select(x => x.Employees)
.FirstOrDefault();
OfType<T>()
is one of the most important methods in EF when it comes to inheritance - you should familiarize yourself with it.
Essentially is filters the items in the query to be of a particular type - very similar to the conditional check your doing in your answer.
It's an IQueryable
method (LINQ-Objects), but in LINQ-Entities (ObjectQuery<T>
), it get's implemented as an INNER JOIN.
The above should work - just make sure you do the eager load <em>after</em> you do the OfType
.
HTH.
Answer2:As always, after posting the question I found <a href="https://stackoverflow.com/questions/1162313" rel="nofollow">this</a> and <a href="https://stackoverflow.com/questions/944332/entity-framework-inheritance-and-include" rel="nofollow">this</a> which has pointed me towards using projection (solution below), but I was hoping to avoid that, so I'm going to leave the question open to see if there is a more elegant solution.
var Employee = caseObjectQuery.Select(x => new{
Employee = x is CaseB ? (x as CaseB).Employee : null
}
).FirstOrDefault();
Just by selecting the Object into memory, EF magically maps the related entities.