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