2011-08-23 49 views
11

考虑:LINQ到实体+包含+匿名类型的问题

类客户端

类项目

客位机票

类回复

客户有项目的一个子集,项目具有门票的子集合,门票具有子集合的回复。

var data = ctx.Set<Ticket>().Include(p => p.Client). 
Select(p => new { Ticket = p, LastReplyDate = p.Replies.Max(q => q.DateCreated)}); 

不起作用。以这种方式选择数据时,不会加载项目和客户端。

我知道如何使它工作。我的问题是为什么它不这样工作?

回答

10

正如拉迪斯拉夫提到的,Include只适用于直接选择Ticket实体。由于您正在投射其他信息,Include会被忽略。

这应该提供一个良好的解决方法:

所有的
var data = ctx.Set<Ticket>() 
    .Select(p => new 
     { 
      Ticket = p, 
      Clients = p.Client, 
      LastReplyDate = p.Replies.Max(q => q.DateCreated) 
     }); 

首先,每张票的客户将可以访问直接从匿名类型的Clients属性。此外,实体框架应该足够聪明,以确认您已经为每个Ticket提取了整个Client集合,因此调用.Ticket.Client也应该可以。

+0

谢谢。这也是我想到的解决方案。 – Jeroen

+2

+1为实际提供解决方案:) – bernhof

+0

我应该指出任何阅读此解决方案的人都不会奇怪地使用此投影返回的实体填充'.Ticket.Client'导航属性,因此通过Ticket对象访问客户端将再次查询数据库。 –

5

因为Include只在直接选择实体时才有效。一旦你做了投影Include被忽略。我不会告诉你为什么,但它只是这样工作。

+0

你认为微软计划改变这种状况? – billy

+0

plus1 *我不会告诉你为什么,但它只是这样工作。* –

2

另一种可能性是使用StriplingWarrior的解决方案,但随后从最终的结果净化中间数据:

var data = ctx.Set<Ticket>() 
    .Select(p => new 
     { 
      Ticket = p, 
      Clients = p.Client, 
      LastReplyDate = p.Replies.Max(q => q.DateCreated) 
     }) 
    .AsEnumerable() 
    .Select(p => new 
     { 
      Ticket = p.Ticket, 
      LastReplyDate = p.LastReplyDate 
     });