Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 打破POCO关系_C#_Asp.net Mvc_Entity Framework_Poco - Fatal编程技术网

C# 打破POCO关系

C# 打破POCO关系,c#,asp.net-mvc,entity-framework,poco,C#,Asp.net Mvc,Entity Framework,Poco,我在破坏两个实体之间的关系时遇到问题。假设我们有一个子实体属于一个父实体,一个父实体有许多子实体。现在,在我的前端,用户可以选择一个单选按钮来选择父项子项属于哪个或选择“无”。我遇到的问题是,当我编辑一个子记录并选择“无”时,它似乎并没有破坏现有的关系 在我的业务逻辑中,我正在执行以下操作: child.Parent = parentRepository.Find(command.ParentID); 如果没有记录与传入的ID匹配,则repository方法返回null,并且当我调试并跨过这一

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

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

child.Parent = parentRepository.Find(command.ParentID);
如果没有记录与传入的ID匹配,则repository方法返回null,并且当我调试并跨过这一行时,选择“None”会给出一个ID 0,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正在执行,但当我在这一行之后检查
child.parent
时,它仍然显示对先前引用的
parent
对象的引用。但有时,它会正确地设置为null。此版本适用于:

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

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

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

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

public int? ParentId { get; set; }
public virtual Parent { get; set; }
modelBuilder.Entity<Child>.HasOptional(d => d.Parent).WithMany(p => p.Children);
context.Children.Include(c => c.Parent).Find(id);
如果您使用的是fluent API,您可以告诉EF父级可以为空,如下所示:

public int? ParentId { get; set; }
public virtual Parent { get; set; }
modelBuilder.Entity<Child>.HasOptional(d => d.Parent).WithMany(p => p.Children);
context.Children.Include(c => c.Parent).Find(id);
这是您可以实际使用的代码,以确保私有字段设置为null

评论回复

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

在存储库Find方法中,加载父对象。您可以通过以下方式实现:

public int? ParentId { get; set; }
public virtual Parent { get; set; }
modelBuilder.Entity<Child>.HasOptional(d => d.Parent).WithMany(p => p.Children);
context.Children.Include(c => c.Parent).Find(id);

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

也粘贴在子模型代码中。如果您在OnModelCreating事件中执行任何fluent API调用,那么也显示它们。好的,因此我按照建议更改了Parent属性以查看发生了什么。当集合被调用时,_parent为null,它将保持null,直到我将光标移到公共虚拟父集合上!然后,我可以成功地将其设置为null。如果我不跳过它,它将保持为null,就像它没有从数据库中提取记录一样,所以当我将它设置为null时,它什么也不做。这是在进行某种惰性加载吗?我本以为当我打电话给child.parent时,EF会给父母补水?看起来我的行为很正常。由于父导航属性是虚拟的,因此将应用延迟加载。第一次调用navigation属性时,相关对象似乎从db中水合。因此,当我使用child.parent=null将其设置为null时;代码真正做的就是从数据库中获取记录。因此,为什么第二个child.parent=null;尝试有效。不管怎样,谢谢你的回答,这真的帮了我的忙。