Причина, по которой вы не можете удалить пузырь, когда каскад отключен, заключается в том, что у вас все еще есть уровни с внешним ключом для пузыря, который вы хотите удалить.
Кроме того, предположим, что вы хотите удалить пузырь2. Пузырь 2 имеет верхний уровень 20.
Пузырь 3 имеет уровень 21, который является подуровнем уровня 20.
Пузырь 4 имеет уровень 22, который является подуровнем уровня 21.
Если вы удалите Bubble 2, следует ли удалить Уровни Bubbles 3 и 4?
Давайте предположим, что ваше программное обеспечение не имеет этих особенностей: нет циклических ссылок на Уровни, и все Уровнииз того же пузыря.
Вы можете аннулировать все LevelIds всех уровней пузыря, которые хотите удалить, перед удалением уровней и пузырей:
// we want to remove Bubble 2
var levelsToRemove = dbContext.Levels.Where(level => level.BubbleId == 2).ToList();
// nullify all levelIds:
foreach (var levelToRemove in levelsToRemove)
{
levelToRemove.LevelId = null;
}
// TODO: maybe we need an extra SaveChanges
// Remove the Levels and the Bubble:
dbContext.Levels.RemoveRange(levelsToRemove);
var bubbleToRemove = dbContext.Find(2); // TODO: exception if not found
dbContext.Bubbles.Remove(bubbleToRemove);
dbContext.SaveChanges();
Правильное решение
Тот факт, что ваш код должен предотвращать циклические ссылки и пузыри с уровнями, которые являются подуровнями уровней других пузырей, должен дать вам понять, что ваша база данных недостаточно нормализована.
Подумайте о том, чтобы дать свою коллекцию уровней.Это может быть отношение «один к нулю или один», или если у всех уровней Bubble 2 есть несколько общих черт, рассмотрите возможность размещения этих вещей в LevelCollection и пусть у вашего пузыря будет ноль или более LevelCollections (один ко многим).).
Каждая коллекция уровней принадлежит ровно одному пузырю.У LevelCollection есть ноль или более уровней.
Теперь гарантируется, что если LevelCollection 42 принадлежит Bubble 2, что все уровни LevelCollection 42 принадлежат Bubble 2. Вы можете удалить внешний ключ BubbleId из Level.
This выиграно 't предотвращает циклические ссылки на уровни, но это предотвратит принадлежность уровней из одного дерева к разным пузырькам
Почему каскадирование пришлось отключить
Обычно, если у вас есть отношение один ко многим, напримерШкола с его многочисленными учениками. При удалении школы вы также хотите автоматически удалить всех своих учеников.Когда включено каскадирование, тогда структура сущности сначала удалит все элементы с внешним ключом к элементу, который вы хотите переместить, прежде чем удалит ваш элемент.
Это невозможно сделать автоматически с Bubbles and Levels
Давайте добавим несколько пузырьков и уровней
Id | Name
Add Bubble with name A => 1 | A
Id | BubbleId | LevelId
Add Level without Parent for Bubble 1 => 10 | 1 | null
Add sub Level of Level 10 Parent for Bubble 2 => 11 | 1 | 10
Now give Level 10 a new LevelId => 10 | 1 | 11
Хорошо, каскадное включение включено, давайте удалим пузырь 1.
Прежде чем объектная структура сможет это сделать, она должна удалить все, что имеет чужойключ к Bubble 1. Итак, сначала нам нужно удалить уровень 10, чего мы не можем, потому что сначала нужно удалить уровень 11.Однако уровень 11 не может быть удален, поскольку уровень 10 не может быть удален и т. Д.
Мы сделали небольшой круг, но вы можете представить, что произойдет, если у вас будет круг с 1000 уровнями.
Ваш код, вероятно, будет препятствовать тому, чтобы вы создали круг, но структура сущностей не может помешать вам сделать это.
Еще одна проблема: предположим, что Bubble 2 имеет уровень 20. Уровень 20 является подчиненнымУровень уровня 21, а уровень 21 имеет внешний ключ для Bubble 1. Если вы удалите Bubble 1, что должно произойти с уровнем Bubble 2?Некоторые люди могут сказать: это становится верхним уровнем Bubble 2, другие могут сказать: нет, Bubble 2 теряет свой уровень.Entity Framework не может определить, что вы хотите, поэтому вам придется сделать это самостоятельно и отключить каскадирование.