Eager loading property of derived class using Include
I have classes like:
Person
{
Name
Address
}
Employee : Person
{
Co开发者_如何学运维mpensation - object
}
Visitor : Person
{
}
If I write linq:
var persons = Context.Persons
.Include("Compensation");
I get error:
A specified Include path is not valid. The EntityType 'Person' does not declare a navigation property with the name 'Compensation'.
It works ok if I do:
var persons = Context.Persons
.OfType<Employee>()
.Include("Compensation");
But I would like to get Employees and visitors in the same query.
Looks like there is a request for this feature on EF4 UserVoice: http://data.uservoice.com/forums/72025-ado-net-entity-framework-ef-feature-suggestions/suggestions/1249289-include-property-of-derived-classes?ref=title
but it does not look like it will get done any time soon.
What is a good workaround for this issue?
You can try it this way:
var persons = Context.Persons
.OfType<Employee>()
.Include("Compensation")
.Concat<Person>(Context.Persons.OfType<Visitor>());
Here's a nice example of how to load Persons
and include Compensation
for Employees
Replace Reference()
by Collection()
for a collection property.
IQueryable<Person> GetPersons()
{
var persons = Context.Persons;
foreach(var entry in persons.OfType<Employee>())
Context.Entry(entry).Reference(e => e.Compensation).Load();
return persons;
}
Not sure either if it's efficient, but it works, and the intention is clearer than with joins.
Based on this SO answer
var employees = context.Persons.OfType<Employee>().Include(x => x.Compensation).ToArray();
var nonEmployees = context.Persons.Except(context.Persons.OfType<Employee>()).ToArray();
var people = employees.Concat(nonEmployees);
This horrible thing works:
var persons = context.Persons
.Concat(context.Employees
.Where(e => e.Compensation.Amount >= 0))
.Concat(context.Visitors
.Where(v => v.SomeProperty == "AlwaysTrue"));
I'm not sure why, but when you filter on an object property, the property's object is eagerly loaded. If you don't want to filter that property, then use a condition that will always be true.
Disclaimer: I have no idea how efficient the resulting query is. I checked the sql generated when I tested this in a slightly more complicated scenario and it was very very large.
精彩评论