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(); 

这将工作