繁体   English   中英

EF 6 保存多个级别的子实体和多个父实体

[英]EF 6 Saving multiple levels of child entities and multiple parents

鉴于此模型:

带孩子的模特

我希望能够在一个 SaveChange 调用中保存关系。 这意味着,我有一个新的或更新的 ContainerParent,以及多个第一级子级,每个子级都可以有 1 或 2 个更深的级别。

问题是,孩子们都有一个自己的钥匙,用于找到它的父母,还有一个容器的钥匙,让容器独立于其层次级别获取所有孩子。

用这个伪代码(在所有实体都被创建的情况下,没有更新)

var newContainerParent = context.ContainerParents.Add(new ContainerParent());
var rootChild = context.Children.Add(new Child());

var secondLevelChild = new Child();
var thirdLevelChild = new Child();
secondLevelChild.Children.Add(thirdLevelChild);

rootChild.Children.Add(secondLevelChild);
newContainerParent.Children.Add(rootChild);

context.SaveChanges();

此代码的问题在于,只有 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)如果您的依赖项中没有循环性,那么完美的树结构,您可以自上而下地逐级保存项目。 我假设你有孩子有参考它的父母,所以根没有参考任何其他项目,你首先保存它,而不是第一级孩子,依此类推。

这需要多个 SaveChanges,但这不是缺点。 无论如何,每个实体都是一个 Insert-SQL-Command,无论您是在 1 SaveChanges 中还是在 100 SaveChanges 中执行此操作。

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

实体框架实际上可以自己找出这种依赖关系并创建新实体插入的顺序,但这在今天没有实现,或者并不完美,尤其是在自引用表上。 保存项目的顺序是随机的。 因此,您必须使用中间 SaveChanges 强制执行订单。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM