EF 6 Сохранение нескольких уровней дочерних объектов и нескольких родителей - PullRequest
0 голосов
/ 15 января 2020

Учитывая эту модель:

Model with child

Я хотел бы иметь возможность сохранить в одном вызове 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, ключ не сохраняется, он возвращается к нулю.

Я исправил это, выполнив все это в 2 этапа, сохранив один раз и затем получить все вновь созданные дочерние элементы и обновить их родительским ключом, снова вызывая SaveChanges.

У меня такое чувство, что я что-то упустил, что мне не нужно экономить дважды.

1 Ответ

0 голосов
/ 15 января 2020

Количество или частота вызовов SaveChange не влияют ни на что, ни на производительность, ни на что. Так почему же вы хотите минимизировать это?

На самом деле, сохранение такой самоссылающейся таблицы с одним SaveChanges невозможно, поскольку при сохранении генерируется идентификатор новой сущности. Итак, сначала вам нужно сохранить его, а затем вы получите идентификатор, который вы можете сохранить в другом объекте. Это может потребовать дальнейших команд обновления для сущности, которую вы только что сохранили.

У вас есть два шанса решить эту проблему.

1) сгенерированные вручную идентификаторы, обработайте все сами, и вы знаете идентификатор перед вашим магазином.

2) Если у вас нет округлости в зависимости, поэтому идеальная древовидная структура позволяет сохранять элементы сверху вниз, уровень за уровнем. Я предполагаю, что у вас есть childs, имеющие ссылку на его родителей, поэтому root не имеет ссылки ни на какие другие элементы, вы сначала сохраняете его, чем потомки 1-го уровня, и т. Д.

Для этого требуется несколько SaveChanges, но это не недостаток. В любом случае это одна команда вставки SQL для каждой сущности, независимо от того, выполняете ли вы ее в 1 SaveChanges или в 100 SaveChanges.

Оба решения избегают команд «Обновить» для сущностей, они выполняют только вставки.

Entity Framework может на самом деле самостоятельно определять эти зависимости и создавать порядок для добавления новых сущностей, но это не реализовано сегодня или не идеально, особенно в таблицах с самоссылкой. Порядок сохранения предметов является случайным. Таким образом, вы должны навести порядок с промежуточными SaveChanges.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...