打破POCO关系

时间:2012-02-07 09:14:05

标签: c# asp.net-mvc entity-framework poco

我在打破两个实体之间的关系方面遇到了问题。假设我们有Child个实体,属于一个ParentParent有许多Child个实体。现在,在我的前端,用户可以选择一个单选按钮来选择Parent Child所属的Child,或者他们可以选择“无”。我遇到的麻烦是,当我编辑child.Parent = parentRepository.Find(command.ParentID); 记录并选择“无”时,它似乎不会破坏现有的关系。

在我的业务逻辑中,我正在做以下事情:

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

如果没有记录与传入的ID匹配,则存储库方法返回null,选择“None”时ID为0但是当我调试并跳过此行时,Child.Parent仍然具有对先前选择的Parent实体的引用。实际上,甚至明确设置Child.Parent = null;似乎没有打破链接。

为了增加我的困惑,这不是一致的行为。偶尔会有相同的代码 打破关系并将Child.Parent设置为null!有人可以指出我正确的方向吗?

更新

我更新了我的代码,以确保repo返回null。

child.parent = null;

调试显示行child.parent 正在执行,但当我在此行后检查Parent时,它仍显示对先前引用的{{1}的引用对象。但是不时地,它正确地设置为null。这个版本有效:

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

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

1 个答案:

答案 0 :(得分:1)

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

如果在子项上公开外键属性,则必须可以为空。因此,如果您的孩子有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。

对评论的回应

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

在您的存储库查找方法中,急切加载父级。你可以这样做:

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

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