Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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# EF 6保存多级子实体和多个父实体_C#_Entity Framework - Fatal编程技术网

C# EF 6保存多级子实体和多个父实体

C# EF 6保存多级子实体和多个父实体,c#,entity-framework,C#,Entity Framework,鉴于这种模式: 我希望能够在一次储蓄中改变储蓄关系。这意味着,我有一个新的或更新的ContainerParent,和多个一级子级,每个子级可以有1或2级更深 问题是,孩子们都有一个自己的密钥,用于查找其父级,还有一个容器的密钥,用于容器独立于其层次结构级别获取其所有孩子 使用此伪代码(如果创建了所有实体,则不更新) 这段代码的问题是,只有rootchild才会为容器设置FK。我还尝试将子对象添加到其子对象父对象和容器中: rootChild.Children.Add(secondLevelCh

鉴于这种模式:

我希望能够在一次储蓄中改变储蓄关系。这意味着,我有一个新的或更新的ContainerParent,和多个一级子级,每个子级可以有1或2级更深

问题是,孩子们都有一个自己的密钥,用于查找其父级,还有一个容器的密钥,用于容器独立于其层次结构级别获取其所有孩子

使用此伪代码(如果创建了所有实体,则不更新)

这段代码的问题是,只有rootchild才会为容器设置FK。我还尝试将子对象添加到其子对象父对象和容器中:

rootChild.Children.Add(secondLevelChild);
newContainerParent.Children.Add(rootChild);
newContainerParent.Children.Add(secondLevelChild);
newContainerParent.Children.Add(thirdLevelChild);
在用新的子容器更新现有容器时,我也遇到同样的问题。我使用父项的已有键设置了所有子项,但是当调用SaveChanges时,该键不会被保存,它会恢复为null

我通过两个步骤来修复它,保存一次,然后获取所有新创建的子项并使用父项更新它们,调用SaveChanges再次更改


我有一种感觉,我错过了一些东西,我不需要保存两次。

SaveChange调用的数量或频率对任何事情都没有影响,对性能也没有影响。那你为什么要最小化它呢

实际上,用一个SaveChanges存储这样一个自引用表是不可能的, 原因保存时生成新实体的ID。因此,您首先需要保存它,然后获得可以存储在另一个实体中的ID。这可能需要对刚存储的实体执行进一步的更新命令

你有两次机会解决这个问题

1) 手动生成的ID,自己处理,在存储之前就知道了ID

2) 如果您的依赖项中没有循环,那么一个完美的树结构将自上而下逐级保存项目。我假设您的孩子有一个对其父母的引用,因此根目录没有对任何其他项目的引用,您首先保存该项,而不是第一级孩子,依此类推

这需要多次保存更改,但这不是缺点。不管是在1个SaveChanges中还是在100个SaveChanges中,每个实体都有一个Insert SQL命令

这两种解决方案都避免对实体执行“更新”命令,它们只执行插入操作


实体框架实际上可以找到这个依赖项本身,并为插入新实体创建一个顺序,但这在今天还没有实现,或者说还不够完善,尤其是在自引用表上。保存项目的顺序是随机的。因此,您必须使用中间保存更改来强制执行顺序。

因此,您建议使用多个保存更改?但是,这将导致对数据库的多次访问,不是吗?SaveChange调用的数量或频率对任何事情都没有影响,对性能没有影响,因此此语句不是正确的是。这与发送的命令完全相同。在一个大字符串中处理1000个插入,并不比处理发送10个字符串慢多少,每个字符串中有100个插入。这就是我们在这里讨论的维度。这纯粹是加法。@ilkerkaran,对,不是绝对性。例如,如果您尚未存储更改,则回放更改会更容易。您不调用SaveChanges,就好像什么都没发生一样。但实际上它只是把巨大的绳子分成更小的绳子。我应该说:服务器处理它所用的时间完全相同。也许10个小请求的开销很小,因为它需要更多的函数调用。Insert通常非常慢,以至于您没有注意到这种开销。在
SaveCahnges
之前,您是否尝试过同时执行代码的第一块和第二块?顺便说一句,我认为这是必要的,但这种关系产生的麻烦比缓解的麻烦多。是的,我想,我可以重新设计数据库来改变它的工作方式,我认为它可能是可变的,但是,模型确实反映了实际情况。是的,这两个代码片段来自代码中的两个不同位置。第一个是当所有内容都是新的时,第二个是当容器存在并且添加了子项时。尝试合并“所有内容都是新的”情况下的代码块。在一些测试之后,您仍然需要将每个子级添加到RootParents,似乎在我更新到最新的EF版本之前它就已经工作了。版本6.4.0打破了这一点。我的生产应用程序在6.3.0上,它在那里工作。
rootChild.Children.Add(secondLevelChild);
newContainerParent.Children.Add(rootChild);
newContainerParent.Children.Add(secondLevelChild);
newContainerParent.Children.Add(thirdLevelChild);