Я бы не стал пытаться подобной логике изнутри сущности.«Дети» либо охотно загружаются в виде списка во время чтения родительского объекта, либо лениво загружаются в контексте контекста при обращении к нему.
При попытке:
var itensToRemove = Children
.Where(x => x.SomeProperty == someProperty)
.ToList();
... это lazy-load all children для родителя до выполнения условия Where.Если это касается многих родителей или больших групп детей, это будет очень неэффективно.
Сущности - это не бизнес-логика, а данные.Если у вас есть требование, например, действие по удалению всех подходящих дочерних элементов из родительской сущности или из нескольких / всех родительских сущностей, то это должно быть выполнено на уровне службы или хранилища, чтобы инкапсулировать бизнес-логику и использовать сущности в качестве представленияданные.
Например, с помощью родительского идентификатора для удаления всех дочерних элементов с параметром "childType", равным "Answer".Если у родителя есть несколько дочерних элементов, а дочерние объекты являются относительно небольшими объектами, вы можете загрузить родительский элемент с его загруженными дочерними элементами и удалить соответствующие объекты, а затем сохранить родительский элемент:
var parent = context.Parents.Where(p => p.ParentId == parentId)
.Include(p => p.Children)
.Single();
var childrenToRemove = parent.Children.Where(c => c.ChildType == "Answer").ToList();
foreach (child in childrenToRemove)
parent.Children.Remove(child);
context.SaveChanges();
Если вы групповыеудаление дочерних элементов от многих / всех родителей или дочерних сущностей имеет громоздкий размер, тогда я хотел бы рассмотреть вопрос о сохранении дочерних элементов как объекта верхнего уровня (с DbSet в контексте) и удалить их напрямую.Предполагается, что между родителем и потомком существует отношение 1-ко-многим (дочерний элемент содержит parentId), а дочерний элемент сам по себе не имеет дочерних элементов:
List<Child> childrenToDelete = new List<Child>();
do
{
childrenToDelete = context.Children
.Where(c => c.ChildType == "Answer")
.Select(c => c.ChildId)
.Take(1000)
.ToList() // Execute the query to get our 1000 IDs. We need Linq2Obj references to continue.
.Select(id => new Child { ChildId = id})
.ToList();
foreach(var child in childrenToDelete)
context.Children.Attach(child);
context.Children.RemoveRange(childrenToDelete);
context.SaveChanges();
} while (childrenToDelete.Any());
Выше загружены соответствующие дочерние идентификаторы и составлены /прикрепите новые ссылки на дочерние объекты, используя эти идентификаторы.Это сохраняет загрузку всех дочерних данных для выполнения удаления.Мы загружаем и удаляем партиями по 1000, чтобы сохранить разумный размер транзакции.Это также необходимо сделать в «чистом» контексте, где родители / дети еще не были загружены, так как это может вызвать проблемы с Attach.Для этого также необходимы соображения по обработке ошибок и соображения по поводу обработки ошибок на полпути, так как будет принят каждый пакет из 1000.
Если вы столкнулись с детьми, у которых есть собственные дочерние ссылки, тогда вы можете посмотреть наопределение контекста и модели сущностей, установленных специально для этой операции, где единственными данными являются обязательные ссылки.(PK и FK), где вы можете загрузить дочерние элементы и связанные с ними сущности из ограниченного контекста для операции и выполнить удаление.Опять же, если это повлияет на большое количество строк, извлекайте данные пакетами.
Последняя альтернатива, которую я могу предложить, - это использовать хранимую процедуру для операции, а затем убедитесь, что любые загруженные родительские объектыв контексте перезагружаются.
Надеемся, что это дает некоторые идеи о том, как обрабатывать ваш сценарий.