2011-06-07 75 views
14

我有类,如:预先加载属性包括

Person 
{ 
    Name 
    Address 
} 

Employee : Person 
{ 
    Compensation - object 
} 

Visitor : Person 
{ 

} 

如果我写LINQ:

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

我得到错误:

A specified Include path is not valid. The EntityType 'Person' does not declare a navigation property with the name 'Compensation'.

它的工作原理确定的,如果我这样做:

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

,但它并不像它会被很快完成任何时间。

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

回答

7

你可以试试这样说:

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

变化的concat行:.Concat (Context.Persons.OfType ());否则不编译。运行时仍然会得到与原始问题相同的错误。 – 2011-06-07 10:14:13

+0

@Ladislav,在我的场景中,Person类型不是抽象的,有的实体只是'Person'既不''Employee'或'Visitor'。你的例子不会给我那些**人的**。试图结合'Person'查询导致OP报告的异常。任何解决方法将非常感激(在我的情况下,它不是'Person',它是'Transaction',但不管)。 – Shimmy 2012-02-28 09:14:22

+0

@Shimmy:以问题为例提出一个单独的问题,并引用这个问题。评论不太适合解决另一个(甚至类似的)问题。 – 2012-02-28 09:22:32

0

这可怕的工作:

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

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

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

+0

这很疯狂......我试图做这项工作,但我的导航属性是一个集合。有关于此的任何想法?我尝试过的所有东西仍然不加载收藏。 – julealgon 2014-08-15 21:22:08

2

下面是如何加载Persons,包括CompensationEmployees

通过Collection()为一个集合属性替换Reference()一个很好的例子。

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
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);