Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.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# 在一对多关系中管理孤儿_C#_Entity Framework - Fatal编程技术网

C# 在一对多关系中管理孤儿

C# 在一对多关系中管理孤儿,c#,entity-framework,C#,Entity Framework,使用实体框架,我在两个表之间建立了父子关系。我正在从联机源检索数据并在本地保存数据 随着父母寿命的延长,孩子的列表在各个方面都会发生变化。可以添加、删除或编辑子项 第1步: 在我的场景中,我得到了一个有1-2个孩子的父母。我使用以下方法创建父/子对象: Parent p = new Parent(); Child c1 = new Child (); c1.Name = "Test1"; Child c2 = new Child (); c2.Name = "Test2"; p.Child

使用实体框架,我在两个表之间建立了父子关系。我正在从联机源检索数据并在本地保存数据

随着父母寿命的延长,孩子的列表在各个方面都会发生变化。可以添加、删除或编辑子项

第1步: 在我的场景中,我得到了一个有1-2个孩子的父母。我使用以下方法创建父/子对象:

Parent p = new Parent();

Child c1 = new Child ();
c1.Name = "Test1";

Child c2 = new Child ();
c2.Name = "Test2";

p.Children.Add(c1);
p.Children.Add(c2);

context.AddToParents(p);
context.SaveChanges();
第二步: 下次我更新child时,2已经不存在了。在本例中,我查询了我的在线来源,并收到了一个不包含子项“Test2”的子项列表。我通过使用linq从parent.Children列表中删除子项来模拟这种情况(因为代码是不可复制的)

子项定义为(在父项中):

发生这种情况时,不会从表中删除子项,但父项为空

第三步: 稍后,当我从在线来源获得更新时,child#2现在又是其中一个孩子。当我将该记录添加回时,我得到一个密钥冲突,因为该记录仍在表中

var parent = (from p in context.Parents
    where p.Name == "Parent"
    select p).FirstOrDefault();

Child child = new Child();
child.Name = "Test2";

parent.Children.Add(child);
context.SaveChanges();
我得到这个错误:

违反主键约束“PK_Slave”。无法在对象“dbo.Child”中插入重复键。重复键值为(Test2)。\r\n语句已终止

我猜我需要在使用新数据更新父记录后从表中删除孤立子记录(在步骤2中),或者-首先使用指向父记录的空指针检查现有子记录,并重用该记录,而不是添加新的子记录。或者两者兼而有之


有更好的设计模式吗?下午我一直在看,答案是避开我。

首先,请注意,您在问题中提到的从不同的源获取数据,然后将其投影到在实体框架上下文中添加/创建的新实例的场景并没有在您提供的代码片段中表示:您向我们提供了反映您工作的sudo代码。虽然我不认为这是步骤1的问题,但我感兴趣的是如何实现步骤2,因为它涉及实例\实体。
c2
是否是从上下文中查询的
Child
的实例?
Children
a
HashTable
on
Parent
类型,并且
p
是该上下文的实例\实体吗?@BrettCaswell-实际上,这不是伪代码。我建立了两个超级简化的测试表,这些代码取自我一直在做的测试。我将编辑上面的帖子来回答你的问题。谢谢你更新你的问题。。实际上,我可以看到,在不删除子记录的情况下,人们可能希望删除记录之间的关系,因此我倾向于相信,删除父记录范围内的子记录的行为就代表了这一点;其中,从
context.Children
中删除实例意味着要删除记录本身。不过,我确实相信有一种
DbConfiguration
或其他方式来指示这种行为。请看,自从我经常使用EF(这是edmx的Db首款)以来,EF的设计有了一些变化。。。您是否从数据库中生成了这些实体\模型?您是否尝试过从父级获取实例(基本上是延迟加载它们)并删除这些实例并保存它们。是否
parent.Children.Where(c=>c.Name==childNameToRemove).FirstOrDefault()
返回实例或某个IKeyLookup类型?。。另外,我建议您添加一个DbConfiguration拦截器,该拦截器将输出到调试控制台,以便您可以在首先执行
SaveChanges
时看到表达式输出,请注意,您在问题中提到的从不同的源获取数据,然后将其投影到在实体框架上下文中添加/创建的新实例的场景并没有在您提供的代码片段中表示:您向我们提供了反映您工作的sudo代码。虽然我不认为这是步骤1的问题,但我感兴趣的是如何实现步骤2,因为它涉及实例\实体。
c2
是否是从上下文中查询的
Child
的实例?
Children
a
HashTable
on
Parent
类型,并且
p
是该上下文的实例\实体吗?@BrettCaswell-实际上,这不是伪代码。我建立了两个超级简化的测试表,这些代码取自我一直在做的测试。我将编辑我的文章来回答你的问题。谢谢你的问题更新。。实际上,我可以看到,在不删除子记录的情况下,人们可能希望删除记录之间的关系,因此我倾向于相信,删除父记录范围内的子记录的行为就代表了这一点;其中,从
context.Children
中删除实例意味着要删除记录本身。不过,我确实相信有一种
DbConfiguration
或其他方式来指示这种行为。请看,自从我经常使用EF(这是edmx的Db首款)以来,EF的设计有了一些变化。。。您是否从数据库中生成了这些实体\模型?您是否尝试过从父级获取实例(基本上是延迟加载它们)并删除这些实例并保存它们。是否
parent.Children.Where(c=>c.Name==childNameToRemove).FirstOrDefault()
返回实例或某个IKeyLookup类型?。。另外,我建议您添加一个DbConfiguration拦截器,该拦截器输出到调试控制台,以便在执行
SaveChanges
var parent = (from p in context.Parents
    where p.Name == "Parent"
    select p).FirstOrDefault();

string childNameToRemove = "Test2";

var child = (from c in context.Children
    where c.Name == childNameToRemove
    select c).FirstOrDefault();

parent.Children.Remove(child);
context.SaveChanges();
var parent = (from p in context.Parents
    where p.Name == "Parent"
    select p).FirstOrDefault();

Child child = new Child();
child.Name = "Test2";

parent.Children.Add(child);
context.SaveChanges();