Какие бывают стратегии удаления зависимостей в Entity Framework
Что проверяют
Понимаете ли вы, что удаление зависимых записей решается в двух местах: в трекере изменений EF Core и в ограничении внешнего ключа в базе, и что эти уровни могут вести себя по-разному. Следом часто спрашивают про мягкое удаление и про ошибку SQL Server о нескольких каскадных путях.
Как отвечать
Поведение задаётся через OnDelete(DeleteBehavior.X) во Fluent API:
Cascade: зависимые удаляются. EF удалит загруженные в контекст, а для остальных миграция создастON DELETE CASCADE. Это дефолт для обязательной связи, где внешний ключ не допускаетnull;ClientSetNull: дефолт для необязательной связи. EF обнулит ключ у загруженных зависимых, а ограничение в базе создаётся без действия, поэтому незагруженные строки дадут ошибку внешнего ключа;SetNull: то же обнуление, но и на уровне базы черезON DELETE SET NULL;RestrictиNoAction: автоматически ничего не меняется, база не даст удалить главную запись, пока на неё ссылаются;ClientCascade: каскад только в памяти. Нужен, когда SQL Server отказывается создать каскад из-за циклов или нескольких каскадных путей.
Отдельно стоят стратегии уровня приложения. Явное удаление: загрузить зависимые и удалить их через RemoveRange до главной записи. Мягкое удаление: флаг IsDeleted, глобальный фильтр HasQueryFilter(e => !e.IsDeleted) и интерсептор, который превращает удаление в обновление. Для массовых операций есть ExecuteDelete() (с EF Core 7): он уходит в базу одной командой мимо трекера, поэтому клиентские каскады не срабатывают, работают только ограничения самой базы.
Где спотыкаются
Думают, что ClientSetNull или ClientCascade защитят данные при любом удалении. Они действуют только на то, что загружено в контекст.
Включают Cascade везде ради удобства. Удаление одного клиента тихо сносит заказы, платежи и историю, а на больших таблицах это ещё и долгая блокировка.
Забывают, как мягкое удаление сочетается со связями. Если у главной сущности есть фильтр, а навигация на неё обязательная, зависимые записи тоже пропадают из выборок с Include, и EF предупреждает об этом при построении модели.