2015-04-17 22 views
2

我有類似如下的模式:如何在Entity Framework中一次爲多個模型顯式加載關係?

class Parent { 
    public int Id { get; set; } 
    public string Name { get;set; } 
    public ICollection<Child> Children { get; set; } 
    public GrandChildren SpecialGrandChild { 
     get { 
      return Children.SelectMany(c => c.Children).Where(...).Single(); 
     } 
    } 
} 

class Child { 
    public int Id { get; set; } 
    public int ParentId { get; set; } 
    public Parent Parent { get; set; } 
    public ICollection<GrandChild> Children { get; set; } 
} 

class GrandChild { 
    public int Id { get; set; } 
    public string Name { get;set; } 
    public int ParentId { get; set; } 
    public Child Parent { get; set; } 
} 

我也有一個涉及所有三個表相當複雜的查詢。從該查詢中,我想提取所有Parent對象,並且我將爲每個對象顯示SpecialGrandChild的屬性。

的問題是,如果我這樣做:

query.Include(p => p.Children.Select(c => c.Children)); 

EF會產生不敬虔的SQL查詢,並採取了大量的時間來構建查詢(在某些情況下超過10秒!)。查詢被緩存,所以進一步的調用要快得多。如果我放棄撥打Include的電話,我不會得到如此糟糕的首次通話表現,但當然我的表現會變差,因爲我會在做M*N+1查詢(對於每個父母,取孩子,並且爲每個孩子取孩子的GrandChildren )。

所以問題是:我可以在一次調用中爲所有加載的父母顯式加載所有Children和GrandChildren嗎?如果是這樣,我該怎麼做?

我試着查詢所有的童車當前加載的父母如下:

var ids = parents.Select(p => p.Id); 
(from c in Childs where ids.Contains(c.ParentId) select c).Include("Children").Load(); 

但這一呼籲並沒有告訴EF所有相關的童車被加載的,因此還是到DB當我訪問關聯屬性。

回答

0

加載你的數據在兩個步驟:

var dbParent = ...; // query all Parent's 
var dbChild = ...; // query all Child's 

var parents = dbParent.Include(p => p.Children).ToList(); 
dbChild.Include(p => p.Children).toList(); 

這應該使父母有父母的所有的列表,而且由於跟蹤的,每個家長都會將其孩子。

如果你必須在家長身上應用過濾條件,你也應該對孩子做過濾條件。

+0

這使我蒙受沉重的成本彙編,兩次:( – felipe

+0

你試過底部''''查詢包含(「Parent.Parent」); ' –

+0

雖然請求數少,但編譯時間仍然很短 – felipe

0

因爲我對父變量和上下文的瞭解不夠多,所以您的父對象可能會附加(或者可能不是)我無法給出準確的答案。 但你要找的應該是這樣的,其中CTX是你的背景和家長的一個實例DbSet屬性是什麼:

IQueryable<Parent> query = ctx.Parents.Include("Children.Children"); 
List<Parent> myTree = query.toList(); 
+0

問題是,如果我添加Include,那麼查詢編譯非常慢......我確實說過我試圖在我的問題中做到這一點 – felipe

相關問題