2013-03-31 38 views
1

我有一個奇怪的問題,我需要一些幫助。我想在EF Code First中做一個簡單的一對多關係。這個想法是有一個CardCategoryCardQuery多個實例。奇怪的懶加載在一對多的關係

這裏是我的CardCategory的定義:

public abstract class CardCategory 
{ 
    [Key, DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)] 
    public int Number { get; set; } 

    [Required] 
    public string Title { get; set; } 

    [InverseProperty("Category")] 
    public virtual ICollection<CardQuery> DataQueries { get; set; } 

    public CardCategory() 
    { 
     // this ensures that the collection is never null (avoiding NullReferenceException). 
     // it's no problem, because the constructor gets called before 
     // data mapping occurs. 
     DataQueries = new List<CardQuery>(); 
    } 
} 

這裏是CardQuery:

public abstract class CardQuery 
{ 
    [Key, DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)] 
    public int Number { get; set; } 

    [InverseProperty("DataQueries")] 
    public virtual CardCategory Category { get; set; } 
} 

奇怪的是,當我嘗試這與我的數據樣本(幾個類別,有幾個疑問關聯),它只能用於一種方式。我能獲得每個查詢的父類是這樣的:

var query = myContext.CardQueries.Find(1); 
var category = query.Category; // this works alright 

但是當我嘗試此相反的方式(以獲取類別中的所有子查詢),我得到的是一個空收集

var category = myContext.CardCategories.Find(1); 
var queries = category.DataQueries; // here is the problem, I get null or empty collection 

也許你想知道CardCategory構造函數中的安全行是否與此有關。 它不,相信我。我嘗試的第一件事是刪除它,我得到的只是一個空而不是空集合。

具有諷刺意味的是,「DataQueries」導航屬性在不同的情況下工作:

var query = myContext.CardQueries.Find(1); 
var category = query.Category; 
var queries = category.DataQueries; // this works, I don't know what's different 

這似乎是EF不知何故未能填充屬性,但我無法找出原因。這從來沒有發生過我,我有點困惑。我會很感激任何建議。

還有就是要清除的最後一件事,我的數據上下文配置是這樣的:

LazyLoadingEnabled = true; 
ProxyCreationEnabled = true; 
AutoDetectChangesEnabled = true; 

感謝您的幫助!

回答

0

嘗試使用IQueryable<T>.Include()

var category = myContext.CardCategories 
    .Include(e => e.DataQueries) 
    .Find(1); 
+0

這很有效,謝謝!但我認爲這不是必要的,因爲延遲加載。這基本上是急切加載。有沒有什麼辦法可以確保每次都加載屬性而不用在查詢中指定它? –

+0

從我的知識不,但我可能是錯的。當我對這個主題進行研究時,大多數文章都說要編寫像GetCardCategoriesIncludingDataQueries()這樣的輔助方法。 –

+0

好吧,我認爲那會暫時做。再次感謝! –

1

我不推薦使用包括,它會導致嚴重的性能與大基地命中。

你的問題在於DataQueries是一個數組,簡單地調用category.DataQueries不會對存儲執行任何查詢(與無法寫myContext.CardQueries並自動獲得結果的方式相同)。您需要明確地調用啓動器,例如ToList()或FirstOrDefault()。

所以,而是採用.INCLUDE試試這個:

var category = myContext.CardCategories.Find(1); 
var queries = category.DataQueries.ToList(); 

這將啓動枚舉,你會得到DataQueries的結果。

作爲旁註:你甚至可以過濾你的category.DataQueries。使用Where語句。

+0

你是對的,那是更好的選擇。乾杯! –

0

我有一個類似但無關的問題。我試圖延遲加載一些嵌套對象,例如訪問Foo.Bar.Baz我的問題是,巴茲從來沒有懶加載,即使收藏酒吧是虛擬的。

事實證明,問題是由Bar,這是私人的ctor造成的。將ctor更改爲保護允許EF爲Bar正確創建代理類並啓用Baz集合的延遲加載。