Ответ 1
Это один из способов удаления элементов в коллекции.
В. Б.
TEntityCollection.ToList().ForEach(Sub(o) ctx.DeleteObject(o))
С#
TEntityCollection.ToList().ForEach(x => ctx.DeleteObject(x))
Затем вам нужно позвонить
ctx.SaveChanges()
Каков правильный способ удаления всех элементов коллекции объекта 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();
Это один из способов удаления элементов в коллекции.
В. Б.
TEntityCollection.ToList().ForEach(Sub(o) ctx.DeleteObject(o))
С#
TEntityCollection.ToList().ForEach(x => ctx.DeleteObject(x))
Затем вам нужно позвонить
ctx.SaveChanges()
Очистить просто удаляет ссылку, но не удаляет entiy.
В вашей ситуации
existing.DocumentItems.Clear();
Все объекты DocumentItems в EntitySet будут очищены, но вам придется удалить/удалить фактический DocumentItem или commit с ошибкой, точно так же, как если бы вы попытались удалить его в базе данных.
Вам нужно прокрутить все ссылки, а затем удалить объект, который вы хотите удалить (если его значение недействительно и в вашей ситуации оно отсутствует)
В качестве альтернативы я видел реализации, которые используют clear, и AssociationChangedHandler для автоматического удаления старого объекта. В основном, если изменение является "удалением/удалением", он вызывает DeleteObject() для осиротевшего объекта.
Да, год, но на незначительной ноте... поскольку DeleteObject принимает один параметр, который является тем же типом, что и аргумент для выражения лямбда, вы можете просто использовать:
entityCollection.ToList().ForEach(ctx.DeleteObject);
Я не уверен, поддерживает ли VB аналогичный синтаксис. Кто-нибудь?
Трюк: при настройке отношений между родителем и ребенком вы должны создать "составной" ключ для ребенка. Таким образом, когда вы сообщите родительу удалить 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();
Готово!
Просто, чтобы ответить на комментарий Nix к ответу,
мне кажется, что метод EntityCollection.Remove отмечает только для удаления отношения, а не сущности, как это делает метод EntityCollection.Clear.
Я знаю, что документация говорит, что и объект будет помечен для удаления, но в моем тесте у меня есть поведение, которое я описал (кто-нибудь может объяснить мне почему?).
Итак, если в вашей концептуальной модели есть ограничение от одного до нескольких внешних ключей, вы не можете сохранить изменения в контексте в хранилище сохраняемости.
Единственный способ, которым я нашел (поскольку я не хочу CascadeDelete), - это цикл через дочерние элементы и вызывать контекст .DeleteObject на каждом из них, тем самым удаляя сущность и связанное с ней отношение.