Подтвердить что ты не робот

Методы EntityCollection Clear() и Remove()

Каков правильный способ удаления всех элементов коллекции объекта EF? В приведенном ниже коде DocumentItems представляет собой набор связанных элементов документа для документа. Этот код работает на Clear(), но не работает на SaveChanges(), потому что связанные элементы связаны с их документом через FK, а FK является обязательным. Поэтому я думаю, что они каким-то образом остаются в воздухе без внешнего ключа после Clear().

Я решаю это с помощью цикла foreach над коллекцией, вызывающей Remove() для каждого элемента, или есть другой способ?

// remove existing document items to prepare for refreshing them
existing.DocumentItems.Clear();
// adds new Document Items
PrepareInvoice(existing, collection);
_repository.SaveChanges();
4b9b3361

Ответ 1

Это один из способов удаления элементов в коллекции.

В. Б.

TEntityCollection.ToList().ForEach(Sub(o) ctx.DeleteObject(o))

С#

TEntityCollection.ToList().ForEach(x => ctx.DeleteObject(x))

Затем вам нужно позвонить

ctx.SaveChanges()

Ответ 2

Очистить просто удаляет ссылку, но не удаляет entiy.

В вашей ситуации

existing.DocumentItems.Clear();  

Все объекты DocumentItems в EntitySet будут очищены, но вам придется удалить/удалить фактический DocumentItem или commit с ошибкой, точно так же, как если бы вы попытались удалить его в базе данных.

Вам нужно прокрутить все ссылки, а затем удалить объект, который вы хотите удалить (если его значение недействительно и в вашей ситуации оно отсутствует)


В качестве альтернативы я видел реализации, которые используют clear, и AssociationChangedHandler для автоматического удаления старого объекта. В основном, если изменение является "удалением/удалением", он вызывает DeleteObject() для осиротевшего объекта.

Ответ 3

Да, год, но на незначительной ноте... поскольку DeleteObject принимает один параметр, который является тем же типом, что и аргумент для выражения лямбда, вы можете просто использовать:

entityCollection.ToList().ForEach(ctx.DeleteObject);

Я не уверен, поддерживает ли VB аналогичный синтаксис. Кто-нибудь?

Ответ 4

Трюк: при настройке отношений между родителем и ребенком вы должны создать "составной" ключ для ребенка. Таким образом, когда вы сообщите родительу удалить 1 или все его дочерние элементы, соответствующие записи будут фактически удалены из базы данных.

Чтобы настроить составной ключ с использованием Fluent API:

modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });

Затем, чтобы удалить связанные дочерние элементы:

var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId);

var childToRemove = parent.Children.First(); // Change the logic 
parent.Children.Remove(childToRemove);

// or, you can delete all children 
// parent.Children.Clear();

_context.SaveChanges();

Готово!

Ответ 5

Просто, чтобы ответить на комментарий Nix к ответу,

мне кажется, что метод EntityCollection.Remove отмечает только для удаления отношения, а не сущности, как это делает метод EntityCollection.Clear.

Я знаю, что документация говорит, что и объект будет помечен для удаления, но в моем тесте у меня есть поведение, которое я описал (кто-нибудь может объяснить мне почему?).

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

Единственный способ, которым я нашел (поскольку я не хочу CascadeDelete), - это цикл через дочерние элементы и вызывать контекст .DeleteObject на каждом из них, тем самым удаляя сущность и связанное с ней отношение.