2012-02-24 49 views
1

即使您只遍歷集合中的第一個項目,延遲加載是否會加載整個集合?或者它只加載在集合中迭代的項目?延遲加載是否會在迭代時加載整個集合?

...或者我不知道我在說什麼嗎?

+0

請張貼一些代碼。 – jrummell 2012-02-24 21:28:47

+1

'ObjectContext'有一個'ObjectMaterialized'事件。你可以聽取這個事件,當你迭代一個集合來找出。 – cadrell0 2012-02-24 21:35:21

+0

@Alex Ford,您對IEnumerable的某些特定情況(實體框架)或一般情況感興趣嗎?即對於一個IEnumerable實現來說,無論什麼時候,只要你問一個項目,都不會停下來獲取7個項目。 – 2012-02-24 22:57:14

回答

4

當您開始迭代集合時,延遲加載會加載整個集合。例如:假設user 1具有作用 「基於role1」, 「role2所」, 「Role3」(user.Rolesvirtual):

var user = context.Users.Single(u => u.Id == 1); 
foreach (var role in user.Roles) // DB query happens here once 
{ 
    Console.WriteLine(role.Name); 
    if (role.Name == "Role1") 
     break; 
} 

雖然你從來沒有訪問Role2Role3他們已經加載仍然。

5

@ Slauma的答案是正確的 - 當導航屬性第一次被訪問時,整個集合被加載。它必須採用「正常」導航屬性的方式,因爲該集合只是常規ICollection而不是IQueryable <>。

但是,如果您不希望加載整個集合,則可以執行兩項操作。如果你有一個可用的上下文,那麼你可以使用Query方法真正地加載懶惰。例如:

foreach (var role in context.Entry(user).Collection(e => e.Roles).Query()) 
{  
    Console.WriteLine(role.Name);  
    if (role.Name == "Role1")  
     break;  
}  

如果您事先知道要查找哪個實體,則可以稍微多加一些。例如,只需加載role1上你可以這樣做:

var role1 = context.Entry(user) 
       .Collection(e => e.Roles) 
       .Query() 
       .Single(r => r.Name == "Role1"); 

這篇文章提供的查詢方法,一些細節:

http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx

如果你想使這更transaprent這樣你不「T需要上下文中運行查詢時可用,然後檢查這些博客文章,介紹如何賺更多的懶惰集合:

http://blog.oneunicorn.com/2011/03/28/extra-lazy-collection-count-with-ef-4-1-part-1/

和更普遍的IQueryable支持的集合:

http://blog.oneunicorn.com/2011/03/30/a-more-general-queryable-collection/

+0

我也發現我的答案是錯誤的一些更多的測試。我想,對懶惰加載部分的太多的一廂情願的想法。好的解釋方式。 – 2012-02-26 21:50:26

+0

你的第一個例子在DB查詢方面會做什麼?它會在每次迭代中爲單個角色生成一個查詢嗎?我實際上已經預料到,當你開始迭代時,只有一個針對* all *角色的查詢。嗯,有趣... – Slauma 2012-02-27 10:19:25