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

Каскадные удаления с помощью Entity Framework - Связанные объекты, удаленные EF

У меня проблема с удалением в Entity Framework. Короче говоря, EF явно пытается удалить объект из базы данных, хотя я специально настроил EF для использования каскадных удалений в базе данных.

Мой дизайн:

У меня есть три типа сущностей, MainEntity, EntityTypeA и EntityTypeB. EF был настроен на использование удаления каскада при удалении EntityTypeA и EntityTypeB. Другими словами, если я удалю экземпляр MainEntity, я хочу, чтобы все связанные экземпляры EntityTypeA и EntityTypeB также были удалены. Я никогда не удаляю EntityTypeA или EntityTypeB, не удаляя их родителя.

Моя проблема заключается в том, что EF явно выдает инструкцию DELETE для EntityTypeA, что приводит к сбою моего приложения.

Вот как выглядит моя модель:

KC43E.png

Отношения имеют следующий нестандартный конфигурационный файл:

  • MainEntity -> EntityTypeA OnDelete: Cascade
  • MainEntity -> EntityTypeB OnDelete: Cascade

Отношение EntityTypeA -> EntityTypeB имеет OnDelete: None

Содержимое базы данных

INSERT INTO MainEntities (Name) values ('Test')
insert into EntityTypeA (MainEntityID) VALUES (1)
insert into EntityTypeB (MainEntityID, EntityTypeAId) VALUES (1, 1)
insert into EntityTypeB (MainEntityID, EntityTypeAId) VALUES (1, 1)

Мой код:

class Program
{
   static void Main(string[] args)
   {
      var context = new Model1Container();
      var mainEntity = context.MainEntities.Include("EntityTypeA").SingleOrDefault();
      context.DeleteObject(mainEntity);
      context.SaveChanges();
   }
}

Что происходит

Когда я вызываю SaveChanges, Entity Framework выполняет следующие действия в базе данных:

exec sp_executesql N'delete [dbo].[EntityTypeA]
where ([Id] = @0)',N'@0 int',@0=1

Это вызывает нарушение внешнего ключа, поскольку в таблице EntityTypeB есть ссылки на экземпляры EntityTypeA.

Вопрос

Почему Entity Framework выдает явное удаление для экземпляра EntityTypeA, хотя я настроил Entity Framework для использования каскадных удалений? Если я удалю Include ( "EntityTypeA" ), он снова начнет работать.

4b9b3361

Ответ 1

Именно так каскадные удаления ведут себя в EF. Установка Cascade в отношении в дизайнере EF инструктирует EF выполнить оператор DELETE для каждого загруженного объекта. Он ничего не говорит о ON CASCADE DELETE в базе данных.

Настройка удаления каскада при использовании EF требует двух шагов:

  • Установить Cascade по отношению к дизайну EF. Этот инструктивный контекст означает, что все загруженные связанные объекты должны быть удалены до удаления родительского объекта. Если этого не произойдет, EF будет генерировать исключение, поскольку внутреннее состояние обнаружит, что загруженные дочерние элементы не связаны с каким-либо существующим родительским объектом, даже если требуется отношение. Я не уверен, что это произойдет до выполнения инструкции delete родительского объекта или после, но нет никакой разницы. EF не перезагружает связанные объекты после выполнения изменений, поэтому он просто не знает о каскадных ударах, вызванных в базе данных.
  • Установить ON CASCADE DELETE по отношению к базе данных. Это даст указание SQL удалить все связанные записи, которые не были загружены в контекст во время удаления родительского элемента.

Реализация каскадных удалений в EF является странной и довольно неэффективной, но это то, как она себя ведет, и если вы хотите ее использовать, вы должны изменить свое приложение, чтобы вести себя правильно в этом сценарии.

Ответ 2

Вместо конструктора EF можно также установить каскадное удаление в FK-ограничениях в базе данных.

Ниже приведены визуальные шаги Sql Server Management Studio (SSMS) по настройке каскадных удалений.

Обратите внимание, что при завершении не забудьте обновить edmx к базе данных, прежде чем пытаться удалить.

enter image description here

Я расскажу об этом более подробно в своем блоге: Cascading Deletes Framework Entity Framework; Установите его из базы данных.