16

I have classes like:

Person
{
   Name
   Address
}

Employee : Person
{
   Compensation - 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?

Eric P
  • 2,907
  • 2
  • 24
  • 33

4 Answers4

7

You can try it this way:

var persons = Context.Persons
                     .OfType<Employee>()
                     .Include("Compensation")
                     .Concat<Person>(Context.Persons.OfType<Visitor>());
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Change concat line to: .Concat(Context.Persons.OfType()); otherwise does not compile. When running still get the same error as in original question. – Eric P Jun 07 '11 at 10:14
  • @Ladislav, In my scenario, the `Person` type isn't abstract, there are entities that are just `Person` neither `Employee` or `Visitor`. Your example won't give me those **`Person`**s. Trying to combine `Person` query causes the exception reported by the OP. Any workarounds will be really appreciated (in my case it's not `Person`, it's `Transaction` but whatever). – Shimmy Weitzhandler Feb 28 '12 at 09:14
  • @Shimmy: Ask a separate question with example of the problem and reference this one. Comments are not well suited for solving another (even similar) problem. – Ladislav Mrnka Feb 28 '12 at 09:22
  • @LadislavMrnka, I thought to but I don't want ppl to mark it as dup. Anyway [here you go](http://stackoverflow.com/q/9479763/75500). – Shimmy Weitzhandler Feb 28 '12 at 10:00
  • 1
    Hey there Ladislav. I've tried this suggestion in my scenario and it is not working. I get an exception saying that `Profile does not declare a navigation property with the name 'Profiles'`. I've created a new question with my requirements [here](http://stackoverflow.com/questions/25331779/how-do-i-perform-eager-loading-of-a-property-on-a-derived-type-in-a-query-for-th). Could you take a look at that? – julealgon Aug 15 '14 at 20:22
4

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

Community
  • 1
  • 1
Jerther
  • 5,558
  • 8
  • 40
  • 59
2
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);
tirexx
  • 33
  • 4
0

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.

Albert Bori
  • 9,832
  • 10
  • 51
  • 78
  • This is crazy... I'm trying to make this work but my navigation property is a collection. Any ideas on that? Everything I've tried still doesn't load the collection. – julealgon Aug 15 '14 at 21:22