2011-12-02 19 views
2

在EF4中是否有一種相對簡單的方法來急切地加載實體的所有相關實體?我在想這個擴展方法是完美的。我有一個使用POCO的場景,其中一個實體具有其他實體的多個導航屬性,而這些導航屬性又具有自己的導航屬性。不用說,這是很多循環和加載來急切地加載一切。當我調用擴展方法時,我想要加載並準備好所有屬性,以便關閉LazyLoading。EF4 - 加載所有相關實體的簡單方法?

喜歡的東西:

using(var context = new MyEntities()) 
{ 
    var widget = context.Widgets.FirstOrDefault(); 
    widget.RecursivelyLoadAllPropertiesForMe() // magical extension method I wished existed 
} 
+0

爲什麼 「循環的很多」?你實際上只需要很多'Include'運算符,可能帶有像Include(「Customer.Contacts」)等虛線路徑。每個實體有一個擴展方法不是問題。但我不確定:你是否正在尋找一種爲所有實體類型加載導航屬性而不明確指定所有這些「Include」的方法? – Slauma

+0

但是,在獲取小部件之前,您必須定義包含。如果您嘗試通過迭代並移動所有導航屬性來加載它,性能將會非常糟糕。 – Andreas

+0

@Slauma準確地說,我不想手動指定所有包含。 – Crackerjack

回答

2

預先加載始終是明確的 - 沒有自動化。您必須爲要加載的所有關係定義包含。如果你不這樣做,你幾乎總是以對每個關係使用新查詢的解決方案結束。

您的擴展方法必須使用:

((EntityCollection<...>)entity.NavigationCollection).Load(); 

如果您需要加載子關係,你也可以撥打:

((EntityCollection<...>)entity.NavigationCollection).CreateSourceQuery() 
                .Include(...) 
                .Execute(); 

但每次調用LoadExecute仍然會創建一個新的查詢數據庫,你必須寫一個代碼來完成這些調用。此外,您必須具有代理實體才能將普通ICollection<...>轉換爲EntityCollection<...>,並且必須加載所有具有通用加載的簡單導航屬性(而不是集合)。

2

這裏的擴展方法,我想出了:

public static void LoadAllProperties<T>(this T entity, ObjectContext context) 
{ 
    Type type = entity.GetType(); 
    context.Refresh(RefreshMode.ClientWins, entity); 
    foreach (var property in type.GetProperties()) 
    { 
     if (property.PropertyType.Name.StartsWith("ICollection")) 
     { 
      context.LoadProperty(entity, property.Name); 
      var itemCollection = property.GetValue(entity, null) as IEnumerable; 
      foreach (object item in itemCollection) 
      { 
       item.LoadAllProperties(context); 
      } 
     } 
    } 
} 

該方法首先通過從上下文刷新實體加載正常的實體屬性值。然後循環遍歷每個屬性,查找屬性集合的導航屬性,並遞歸加載集合中的每個項目。這對我所需要的並且不需要使用代理或包含的情況非常有效。

用法:

using(var context = new MyEntities()) 
{ 
    context.ContextOptions.ProxyCreationEnabled = false; 
    var widget = context.Widgets.FirstOrDefault(); 
    widget.LoadAllProperties(context); 
} 
+4

但是這段代碼的性能非常差。 –

+0

@LadislavMrnka我同意,我只會在你知道你沒有加載大量對象時才使用它。 – Crackerjack

-1

是的,有!剛去:

widget.Load() 

或者,如果你去:

var widget = context.Widgets.FirstOrDefault().Include("SomeRelatedEntities").Include("OtherRelatedEntities"); 

你不會需要!

-1

step 1
context.DataContext.ContextOptions.ProxyCreationEnabled = true; context.DataContext.ContextOptions.LazyLoadingEnabled = true;

第2步 添加虛擬關鍵字navigator屬性

public class BankBranche 
    { 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public string Code { get; set; } 

    public int BankId { get; set; } 

    public virtual Address Address { get; set; } 

    public virtual Bank Bank { get; set; } 

}

相關問題