破坏 POCO 关系

发布于 2025-01-03 03:47:45 字数 1284 浏览 2 评论 0原文

我在破坏两个实体之间的关系时遇到问题。假设我们有一个 Child 实体,它属于一个 Parent,一个 Parent 拥有许多 Child 实体。现在,在我的前端,用户可以选择一个单选按钮来选择 Child 属于哪个 Parent,或者他们可以选择“None”。我遇到的问题是,当我编辑 Child 记录并选择“无”时,它似乎并没有破坏现有关系。

在我的业务逻辑中,我正在执行以下操作:

child.Parent = parentRepository.Find(command.ParentID);

如果没有记录与传入的 ID 匹配,则存储库方法返回 null,并且选择“无”会给出 0 ID,但当我调试并跨过此行时,Child.Parent 仍然有一个引用先前选择的父实体。事实上,甚至显式设置 Child.Parent = null;似乎没有破坏链接。

更让我困惑的是,这不是一致的行为。时不时地,相同的代码确实会破坏关系并将Child.Parent设置为null!有人可以指出我正确的方向吗?

更新

我更新了代码以确保存储库返回 null。

Parent parent = parentRepository.Find(command.ParentID);
if (parent == null)
    child.parent = null;
else
    child.parent = parent;

调试显示行 child.parent = null; is 正在执行,但是当我在该行之后检查 child.parent 时,它仍然显示对先前引用的 Parent 对象的引用。但时不时地,它会被正确设置为 null。此版本有效:

Parent parent = parentRepository.Find(command.ParentID);
if (parent == null)
{
    child.parent = null;
    child.parent = null;
}
else
    child.parent = parent;

为什么我必须将其设置为 null 两次才能获得一致的行为?我是否必须以某种方式显式声明 ParentChild 实体上可为空?

I'm experiencing a problem in breaking a relationship bteween two entities. Let's say we have a Child entity which belongs to one Parent, a Parent has many Child entities. Now in my front end a user can select a radio button to choose which Parent the Child belongs to or they can choose "None". The trouble I'm having is that when I edit a Child record and select "None", it doesn't seem to break an existing relationship.

In my business logic I am doing the following:

child.Parent = parentRepository.Find(command.ParentID);

The repository method returns null if no record matches the passed in ID, and selecting "None" gives an ID of 0 yet when I debug and step over this line, Child.Parent still has a reference to the previously chosen Parent entity. In fact, even explicitly setting Child.Parent = null; doesn't seem to break the link.

To add to my confusion, this isn't consistant behaviour. Every now and then the same code does break the relationship and set Child.Parent to null! Can someone please point me in the right direction?

UPDATE

I updated my code to ensure that the repo is returning null.

Parent parent = parentRepository.Find(command.ParentID);
if (parent == null)
    child.parent = null;
else
    child.parent = parent;

Debugging shows that the line child.parent = null; is being executed, yet when I check child.parent after this line, it still shows a reference to the previously referenced Parent object. But every now and then, it is correctly setting to null. This version works:

Parent parent = parentRepository.Find(command.ParentID);
if (parent == null)
{
    child.parent = null;
    child.parent = null;
}
else
    child.parent = parent;

Why do I have to set it to null twice to get consistant behaviour? Do I have to explicitly declare that Parent is nullable on the Child entity somehow?

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

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

发布评论

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

评论(1

寻找一个思念的角度 2025-01-10 03:47:45

是的,您确实需要声明父级可为空。

如果您在子项上公开外键属性,则它必须可为空。因此,如果您的孩子有 ParentId 属性,它应该如下所示:

public int? ParentId { get; set; }
public virtual Parent { get; set; }

如果您使用流畅的 API,您可以像这样告诉 EF 父级可为空:

modelBuilder.Entity<Child>.HasOptional(d => d.Parent).WithMany(p => p.Children);

或者像这样,如果您从主体端而不是从主体端声明关系依赖端:

modelBuilder.Entity<Parent>.HasMany(p => p.Children).WithOptional(d => d.Parent);

奇怪的是child.Parent需要设置为null两次。您是否尝试过单步查看代码以了解原因?您还可以对 Parent 属性尝试此操作,以准确了解发生了什么:

private Parent _parent;
public virtual Parent
{
    get { return _parent; }
    set { _parent = value; }
}

这是您实际上可以进入的代码,以确保私有字段设置为 null。

对评论的回应

听起来确实存在延迟加载的问题。试试这个。

在存储库 Find 方法中,立即加载父级。你可以用这样的方法来做到这一点:

context.Children.Include(c => c.Parent).Find(id);

这将使 child.Parent 已经加载到上下文中,并且设置为 null 一次就足够了。

Yes, you do need to declare that the parent is nullable.

If you expose a foreign key property on the child, it has to be nullable. So if your child has a ParentId property, it should look like this:

public int? ParentId { get; set; }
public virtual Parent { get; set; }

If you are using the fluent API, you can tell EF that the parent is nullable like this:

modelBuilder.Entity<Child>.HasOptional(d => d.Parent).WithMany(p => p.Children);

Or like this, if you declare the relationship from the principal end rather than the dependent end:

modelBuilder.Entity<Parent>.HasMany(p => p.Children).WithOptional(d => d.Parent);

It is strange that the child.Parent needs to be set to null twice. Have you tried stepping into the code to see why? You could also try this for your Parent property, to see exactly what is going on:

private Parent _parent;
public virtual Parent
{
    get { return _parent; }
    set { _parent = value; }
}

This is code you can actually step into, to make sure that the private field is being set to null.

Response to comment

It does sound like there is an issue with lazy loading going on. Try this.

In your repository Find method, eager load the parent. You can do that with something like this:

context.Children.Include(c => c.Parent).Find(id);

This would make child.Parent already loaded on the context, and setting to null once should suffice.

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