4

我使用VS2010,EF4功能CTP(最新版本),以及POCO對象,如下面的例子:EF4 POCO一對多導航屬性爲null

class Person 
{ 
public int ID { get; set; } 
public string Name { get; set; } 
public virtual IList<Account> Accounts { get; set; } 
... 
} 

class Account 
{ 
public string Number { get; set; } 
public int ID { get; set; } 
... 
} 

爲簡便起見,假設下面的context是EF4的上下文對象。我有實體類型和數據庫之間的DBML映射,我使用它像這樣沒有問題:

Person doug = context.Persons.CreateObject(); 
doug.Name = "Doug";  
context.Add(doug); 
context.Save(); 
doug.Accounts.Add(new Account() { Name = "foo" }); 
context.Save(); // two calls needed, yuck 

在這一點上,該數據庫有一個名爲「道」一個人的記錄,並且帳戶記錄「富」。我可以查詢並將這些記錄恢復正常。但是,如果我嘗試在之前添加帳戶,我保存該人員,則帳戶列表爲空(代理尚未在該特性上創建實例)。看下面的例子:

Person doug = context.Persons.CreateObject(); 
doug.Name = "Doug"; 
doug.Accounts.Add(new Account() { Name = "foo" }); // throws null reference exception 
context.Add(doug); 
context.Save(); 

有沒有其他人遇到過這個?更好的是,有沒有人找到一個好的解決方案?

回答

1

ISTM,如果你期望框架爲你做這一切,那麼你不會真的有一個「POCO」,你會嗎?帶上面的代碼,帶上你的Person類。如果EF沒有參與,那麼你會期望Accounts屬性的狀態在施工之後,沒有構造函數?在我看來,CLR將保證它們爲空。

是的,代理可以在必要時初始化DB值,但在EF中,「POCO」其實意味着「Plain」。不是「我們假裝運行時生成的代碼包含的東西是'Plain'」。

+1

我已經編輯我的問題澄清,我不是問的構造方案,但'context.Persons.CreateObject();'行爲。我的困惑是,如果框架在保存對象後要「擁有」那些導航屬性,爲什麼它在創建實體實例時不這樣做?我將集合初始化放在我的實體的構造函數中沒有問題,但是如果框架期望這些集合是'null',那麼看起來我將該對象置於壞狀態。 – 2010-01-05 19:33:33

2

是的,是的!

當您新建POCO時(與上下文中的CreateObject相反),則不會爲您提供代理服務器。這可能看起來很明顯,但在追查類似問題時,我必須明確提醒自己這種行爲。 (我知道這不是你在問題中描述的情況,但應該承認整體問題)。

初始化POCO的構造函數中的集合不會影響EF4代理的正常延遲加載行爲,這與我在我自己的測試中觀察到的行爲並無關係。

好的,所有這些都說了,我現在看到您對以前的答案的評論 - 爲什麼我沒有代理地址集合,當我從我的上下文請求一個新的人?你是否在上下文中啓用了延遲加載?看到我們如何處理導航屬性,我可以看到關閉延遲加載的位置可能會在這種情況下產生變化。

3
Person doug = context.Persons.CreateObject(); 

doug.Name = "Doug"; 

context.Add(doug); 
doug.Accounts.Add(new Account() { Name = "foo" }); 
context.Save(); 

這將工作