Entity Framework.Remove() vs..DeleteObject()

Вы можете удалить элемент из базы данных с помощью EF, используя следующие два метода.

Первый находится на EntityCollection, а второй - на ObjectContext.

Когда каждый должен использоваться?

Можно ли выбрать другого?

Remove() возвращает bool и DeleteObject() возвращает void.

Ответ 1

Как правило, не правильно, что вы можете "удалить элемент из базы данных" с помощью обоих методов. Если быть точным, это так:

  • ObjectContext.DeleteObject(entity) помещает объект как Deleted в контексте. (После этого EntityState Deleted.) Если вы вызываете SaveChanges, то EF отправляет SQL-запрос DELETE в базу данных. Если никакие ссылочные ограничения в базе данных не будут нарушены, объект будет удален, в противном случае создается исключение.

  • EntityCollection.Remove(childEntity) отмечает связь между родителем и childEntity как Deleted. Если сам childEntity удаляется из базы данных, и что именно происходит, когда вы вызываете SaveChanges, зависит от вида отношения между двумя:

    • Если отношение необязательно, то есть внешний ключ, который ссылается от дочернего на родительский элемент в базе данных, допускает значения NULL, этот иностранец будет иметь значение null и если вы call SaveChanges это значение NULL для childEntity будет записано в базу данных (т.е. связь между двумя удаленными). Это происходит с оператором SQL UPDATE. Нет инструкции DELETE.

    • Если отношение требуется (FK не разрешает значения NULL), а отношение не идентифицирует (что означает, что внешний ключ не является частью дочернего (составного) первичного ключа), вы должны либо добавить ребенка к другому родительскому элементу, либо вы должны явно удалить дочерний элемент (затем DeleteObject). Если вы не выполняете какие-либо из этих действий, нарушение ссылок будет нарушено, и EF будет генерировать исключение, когда вы вызываете SaveChanges - печально известное "Отношения не могут быть изменены, поскольку один или несколько свойств внешнего ключа не является нулевым" исключение или подобное.

    • Если отношение идентифицирует (обязательно требуется, то, поскольку любая часть первичного ключа не может быть NULL), EF отметит childEntity как Deleted. Если вы вызываете SaveChanges, оператор SQL DELETE будет отправлен в базу данных. Если никакие другие ссылочные ограничения в базе данных не будут нарушены, объект будет удален, в противном случае создается исключение.

На самом деле я немного запутался в разделе Заметки на странице MSDN, в котором вы указали: "Если отношение имеет ссылочный ограничение целостности, вызов метода Remove на зависимом объекте означает как отношение, так и зависимый объект для удаления.". Это кажется нечетким или даже неправильным для меня, потому что все три случая выше имеют "ограничение ссылочной целостности", но только в последнем случае ребенок фактически удален. (Если они не подразумевают под "зависимым объектом" объект, который участвует в идентифицирующей взаимосвязи, которая была бы необычной терминологией, хотя.)

Ответ 2

Если вы действительно хотите использовать Deleted, вам придется сделать ваши внешние ключи обнуляемыми, но тогда вы попадете в сиротские записи (что является одной из основных причин, по которым вы не должны делать этого в первом место). Поэтому просто используйте Remove()

ObjectContext.DeleteObject(entity) отмечает объект как удаленный в контексте. (После этого EntityState удаляется.) Если вы вызываете SaveChanges после этого, EF отправляет инструкцию SQL DELETE в базу данных. Если никакие ссылочные ограничения в базе данных не будут нарушены, объект будет удален, в противном случае создается исключение.

EntityCollection.Remove(childEntity) отмечает взаимосвязь между parent и childEntity как Deleted. Если сам childEntity удаляется из базы данных, и что именно происходит при вызове SaveChanges, зависит от типа отношения между двумя:

Следует отметить, что установка .State = EntityState.Deleted не вызывает автоматически обнаруженное изменение. (archive)