2011-07-28 60 views
1

這是真的很煩EF代碼第一個問題 - 相關實體未加載

我有這樣的事情:

class Person { 
    ..properties id, name etc.. 
} 
class Task { 
    ..properties id, name etc.. 
    Person Moderator {get;set} 
} 
public class DataModel : DbContext { 
     public DbSet<Task> Tasks { get; set; } 
     public DbSet<Person> People { get; set; } 
} 

我可以創建新任務,新加入的使用者對象的任務和保存,我可以看到正確保存在sql後端的數據 - 每個保存的任務都有正確的人員ID保存 與它和具有該ID的人也被保存回來。

但是當我嘗試找回任務時,person對象始終爲空。

using (DataModel db = new DataModel()) { 
    Task t = db.Tasks.SingleOrDefault(p => p.Id == 22); 
    assert(t.Name.Lenght>0) 
    assert(t.Moderator != null) // always null!!!!!! 
    .... 
} 

我該怎麼做才能讓整個對象圖回購?我是否必須在SingleorDefault調用中加入?似乎有點不對。

難道我提到這是真的是煩人。

TIA,

回答

3

兩種選擇適合你。默認情況下,代碼first/dbContext模型會返回一個從您的模型派生的代理對象(這對於瞭解何時遇到JSON序列化問題很重要)。代理對象使用關聯的延遲加載,但僅在特定情況下使用。 Moderator屬性必須聲明爲虛擬的,以便代理可以覆蓋它併爲您執行延遲加載。

但是,延遲加載會產生一個叫做Select N+1的問題。如果在大多數情況下你只需要任務而不是主持人,這不會是一個問題。但是,如果您經常顯示任務列表及其關聯的主持人,則除了原始列表中的1之外,您將不得不針對該列表中的每個任務運行數據庫的額外往返行程(例如,對於100個任務的列表你會做101個查詢來顯示任務和他們的主持人)。

爲了解決這個問題,EF provides the Include operator,這強制關係加載。使用它作爲這樣

任務T = db.Tasks.Include(T => t.Moderator).SingleOrDefault(p值=> p.Id == 22);

希望這會有所幫助。

1

您有懶加載關閉您Moderator屬性,因此,如果你明確地這樣做使用Load()它只會被加載。

您可以強制EF使用Include()方法在查詢中這樣急切地加載相關Person實體:

Task t = db.Tasks.Include(x => x.Moderator).SingleOrDefault(p => p.Id == 22) 

有在this article一個很好的概述。