EF4 POCO 一对多导航属性为空

发布于 2024-08-16 16:13:32 字数 995 浏览 3 评论 0原文

我使用的是 VS2010、EF4 功能 CTP(最新版本)和 POCO 对象,如下例所示:

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

此时,数据库有一个名为“Doug”的人员记录和一个帐户记录“foo”。我可以很好地查询并取回这些记录。但是,如果我在保存人员之前尝试添加帐户,则帐户列表将为空(代理尚未在该属性上创建实例)。请参阅下一个示例:

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

还有其他人遇到过这种情况吗?更好的是,有人找到好的解决方案吗?

I'm using VS2010, EF4 feature CTP (latest release), and POCO objects, such as the example below:

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; }
 ...
}

For the sake of brevity, assume context below is the context object for EF4. I have a dbml mapping between entity types and the database, and I use it like this with no problem:

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

At this point, the database has a Person record with the name "Doug", and an account record "foo". I can query and get those record back just fine. But if I instead try to add the account before I save the Person, the Accounts list is null (the proxy hasn't created an instance on that property yet). See the next example:

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

Has anybody else encountered this? Even better, has anyone found a good solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

绝不服输 2024-08-23 16:13:32
Person doug = context.Persons.CreateObject();

doug.Name = "Doug";

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

这会起作用

Person doug = context.Persons.CreateObject();

doug.Name = "Doug";

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

This will work

你的呼吸 2024-08-23 16:13:32

是的,是的!

当您新建 POCO 时(与从上下文中创建对象相反),不会为您提供任何代理。这似乎是显而易见的,但在追查类似问题时,我必须明确提醒自己这种行为。 (我知道这不是您在问题中描述的情况,但应该承认总体问题)。

根据我在自己的测试中观察到的情况,在 POCO 构造函数中初始化集合不会干扰正确的 EF4 代理延迟加载行为。

好吧,说了这么多,我现在看到了您对之前答案的评论——为什么当我从上下文中请求新的 Person 时没有代理地址集合?您是否在上下文中启用了延迟加载?看看我们如何处理导航属性,我可以看到关闭延迟加载可能会在这种情况下产生影响。

Yes and yes!

When you new the POCO up (as opposed to CreateObject from the Context), no proxies are provided for you. This may seem obvious, but I had to explicitly remind myself of this behavior when chasing a similar issue down. (I know this isn't the situation you described in the question, but the overall issue should be acknowledged).

Initializing collections in the constructor of the POCO does not interfere with proper EF4 proxy lazy-loading behavior, from what I've observed in my own testing.

OK, all this being said, I now see your comment to the previous answer -- why don't I have a proxied Addresses collection when I request a new Person from my context? Do you have lazy loading enabled on the context? Seeing how we're dealing with navigation properties, I could see where having lazy loading turned off may make a difference in this situation.

寻梦旅人 2024-08-23 16:13:32

ISTM,如果您希望框架为您完成所有这一切,那么您就不会真正拥有“POCO”,不是吗?使用您的 Person 类,使用上面的代码。如果不涉及 EF,您期望在构造之后(没有构造函数)Accounts 属性的状态是什么?在我看来,CLR 将保证它们为空。

是的,代理可以在需要具体化 DB 值时对其进行初始化,但在 EF 中,“POCO”实际上意味着“Plain”。不是“充满运行时生成的代码的东西,我们假装是‘简单的’”。

ISTM that if you expect the framework to do all this for you then you wouldn't really have a "POCO", would you? Take your Person class, with the code above. What would you expect the state of the Accounts property to be after construction, with no constructor, if the EF weren't involved? Seems to me that the CLR will guarantee them to be null.

Yes, proxies can initialize this when necessary for materialization of DB values, but in the EF, "POCO" actually means "Plain". Not "something packed with runtime-generated code which we pretend is 'Plain'".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文