实体框架.Remove()与.DeleteObject()

时间:2013-07-18 12:36:06

标签: c# database entity-framework orm

您可以使用以下两种方法使用EF从数据库中删除项目。

第一个位于EntityCollection,第二个位于ObjectContext

什么时候应该使用?

是否优先考虑另一个?

Remove()返回boolDeleteObject()返回void

2 个答案:

答案 0 :(得分:269)

使用这两种方法“从数据库中删除项目”通常不正确。确切地说是这样的:

  • ObjectContext.DeleteObject(entity)在上下文中将实体标记为Deleted 。 (此后EntityStateDeleted。)如果之后调用SaveChanges,EF会向数据库发送SQL DELETE语句。如果违反了数据库中的引用约束,则将删除该实体,否则将引发异常。

  • EntityCollection.Remove(childEntity)父项与childEntity之间的关系标记为Deleted 。如果从数据库中删除childEntity本身,并且在调用SaveChanges时确实发生了什么,取决于两者之间的关系类型:

    • 如果关系是可选,即从子级引用到数据库中的父级的外键允许NULL值,则此外部将设置为null并且如果您调用SaveChangesNULL的{​​{1}}值将写入数据库(即删除两者之间的关系)。这发生在SQL childEntity语句中。没有UPDATE声明。

    • 如果关系必需(FK不允许DELETE值)并且关系无法识别(这意味着外键不是子(复合)主键的一部分)您必须将子项添加到另一个父项,或者必须显式删除子项(然后使用NULL)。如果您不执行任何这些操作,则会违反参照约束,当您致电DeleteObject时,EF会抛出异常 - 臭名昭着的The relationship could not be changed because one or more of the foreign-key properties is non-nullable异常或类似情况。< / p>

    • 如果关系识别(它必然必需,那么因为主键的任何部分都不能是SaveChanges),EF会标记{ {1}}也是NULL。如果您调用childEntity,则会将SQL Deleted语句发送到数据库。如果数据库中没有违反其他参照约束,则实体将被删除,否则将引发异常。

我实际上对你链接的Remarks section on the MSDN page感到有点困惑,因为它说:“如果关系具有参照完整性约束,则在依赖对象上调用Remove方法标记关系和依赖对象删除。“。这对我来说似乎是不准确甚至是错误的,因为上面的所有三种情况都有“引用完整性约束”,但只有在最后一种情况下才会删除子项。 (除非它们的意思是“依赖对象”,这是一个参与识别关系的对象,虽然这可能是一个不寻常的术语。)

答案 1 :(得分:13)

如果你真的想使用Deleted,你必须让你的外键可以为空,但是你最终会得到孤立的记录(这是你不应该在第一次做到这一点的主要原因之一)地点)。所以只需使用Remove()

ObjectContext.DeleteObject(entity)在上下文中将实体标记为已删除。 (之后删除了EntityState。)如果之后调用SaveChanges,EF会向数据库发送SQL DELETE语句。如果违反了数据库中的引用约束,则将删除该实体,否则将引发异常。

EntityCollection.Remove(childEntity)将parent和childEntity之间的关系标记为已删除。如果从数据库中删除了childEntity本身,并且在调用SaveChanges时究竟发生了什么,取决于两者之间的关系类型:

值得注意的是设置.State = EntityState.Deleted does not trigger automatically detected change. archive