使用Include来获取派生类的加载属性

时间:2011-06-07 09:33:49

标签: entity-framework inheritance ef-code-first

我有类似的课程:

Person
{
   Name
   Address
}

Employee : Person
{
   Compensation - object
}

Visitor : Person
{

}

如果我写linq:

var persons = Context.Persons
                .Include("Compensation");

我收到错误:

  

指定的包含路径无效。   EntityType'Person'没有   用。声明一个导航属性   名称'赔偿'。

如果我这样做,它就可以了:

var persons = Context.Persons
                .OfType<Employee>()
                .Include("Compensation");

但我想在同一个查询中找到员工和访客。

看起来EF4 UserVoice上有此功能的请求: http://data.uservoice.com/forums/72025-ado-net-entity-framework-ef-feature-suggestions/suggestions/1249289-include-property-of-derived-classes?ref=title

但它看起来不会很快就会完成。

这个问题有什么好的解决方法?

4 个答案:

答案 0 :(得分:7)

你可以这样试试:

var persons = Context.Persons
                     .OfType<Employee>()
                     .Include("Compensation")
                     .Concat<Person>(Context.Persons.OfType<Visitor>());

答案 1 :(得分:3)

以下是如何为Persons

加载Compensation并包含Employees的一个很好的示例

Reference()替换为Collection()以获取集合属性。

IQueryable<Person> GetPersons()
{
    var persons = Context.Persons;
    foreach(var entry in persons.OfType<Employee>())
        Context.Entry(entry).Reference(e => e.Compensation).Load();
    return persons;
}

不确定它是否有效,但是它有效,并且意图比连接更清晰。

基于此SO answer

答案 2 :(得分: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);

答案 3 :(得分:0)

这件可怕的事情有效:

var persons = context.Persons
                .Concat(context.Employees
                    .Where(e => e.Compensation.Amount >= 0))
                .Concat(context.Visitors
                    .Where(v => v.SomeProperty == "AlwaysTrue"));

我不知道为什么,但是当您过滤对象属性时,会急切地加载该属性的对象。如果您不想过滤该属性,请使用始终为真的条件。

免责声明:我不知道生成的查询效率如何。我检查了在一个稍微复杂的场景中测试时生成的sql,它非常非常大。