您可以通过以下两种方法使用 EF 从数据库中删除项目。
第一个在 上EntityCollection
,第二个在 上ObjectContext
。
什么时候应该使用每个?
一个比另一个更受欢迎吗?
Remove()
返回 abool
并DeleteObject()
返回void
。
您可以通过以下两种方法使用 EF 从数据库中删除项目。
第一个在 上EntityCollection
,第二个在 上ObjectContext
。
什么时候应该使用每个?
一个比另一个更受欢迎吗?
Remove()
返回 abool
并DeleteObject()
返回void
。
您可以使用这两种方法“从数据库中删除项目”通常是不正确的。准确地说是这样的:
ObjectContext.DeleteObject(entity)
将实体标记为Deleted
在上下文中。(EntityState
就是Deleted
在那之后。)如果您SaveChanges
之后调用,EF会向DELETE
数据库发送一条 SQL 语句。如果没有违反数据库中的引用约束,实体将被删除,否则抛出异常。
EntityCollection.Remove(childEntity)
标记parent 和as之间的关系childEntity
Deleted
。如果childEntity
从数据库中删除自身,那么调用时究竟会发生什么SaveChanges
取决于两者之间的关系类型:
如果关系是可选的,即数据库中从孩子到父母的外键允许NULL
值,这个外键将被设置为空,如果你调用SaveChanges
这个NULL
值childEntity
将被写入数据库(即之间的关系这两个被删除)。这发生在 SQLUPDATE
语句中。不会出现任何DELETE
语句。
如果需要关系(FK 不允许NULL
值)并且关系无法识别(这意味着外键不是子项(复合)主键的一部分),则必须将子项添加到另一个父项或您必须明确删除孩子(DeleteObject
然后)。如果您不执行任何这些操作,则会违反引用约束,并且 EF 将在您调用时抛出异常SaveChanges
- 臭名昭著的“无法更改关系,因为一个或多个外键属性不可为空”异常或相似的。
如果关系正在识别(它是必需的,因为主键的任何部分都不能是NULL
),EF 也将标记childEntity
为Deleted
。如果调用SaveChanges
SQLDELETE
语句,就会发送到数据库。如果没有违反数据库中的其他引用约束,实体将被删除,否则抛出异常。
实际上,我对您链接的 MSDN 页面上的备注部分感到有些困惑,因为它说:“如果关系具有引用完整性约束,则在依赖对象上调用 Remove 方法会将关系和依赖对象都标记为删除。 ”。这对我来说似乎不精确甚至是错误的,因为上述所有三种情况都有一个“参照完整性约束”,但只有在最后一种情况下,孩子实际上被删除了。(除非他们用“依赖对象”表示参与识别关系的对象,但这将是一个不寻常的术语。)
如果你真的想使用 Deleted,你必须让你的外键可以为空,但是你最终会得到孤立的记录(这是你一开始不应该这样做的主要原因之一)。所以只需使用Remove()
ObjectContext.DeleteObject(entity)在上下文中将该实体标记为已删除。(它的 EntityState 在那之后被删除。)如果你在之后调用 SaveChanges,EF 会向数据库发送一条 SQL DELETE 语句。如果没有违反数据库中的引用约束,实体将被删除,否则抛出异常。
EntityCollection.Remove(childEntity)将 parent 和 childEntity 之间的关系标记为 Deleted。如果 childEntity 本身已从数据库中删除,那么调用 SaveChanges 时究竟发生了什么取决于两者之间的关系类型:
值得注意的是,设置.State = EntityState.Deleted
不会触发自动检测到的更改。 (存档)