2011-08-23 60 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 
     });