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

Sam*_*ach 138 c# database orm entity-framework

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

第一个是EntityCollection第二个,第二个是ObjectContext.

什么时候应该使用?

一个优先于另一个吗?

Remove()返回a boolDeleteObject()返回void.

Sla*_*uma 270

使用这两种方法可以" 从数据库中删除项目 "通常不正确.确切地说,它是这样的:

  • ObjectContext.DeleteObject(entity)在上下文中标记实体Deleted.(它EntityStateDeleted后).如果你打电话SaveChanges后EF发送SQL DELETE语句到数据库.如果违反了数据库中的引用约束,则将删除该实体,否则将引发异常.

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

    • 如果关系是可选的,即从子级引用到数据库中的父级的外键允许NULL值,则此外部将被设置为null,如果调用SaveChangesNULL值,则将该值childEntity写入数据库(即两个被删除).这发生在SQL UPDATE语句中.没有DELETE发表声明.

    • 如果需要关系(FK不允许NULL值)且关系未识别(这意味着外键不是子(复合)主键的一部分),则必须将子项添加到另一个父项或你必须明确删除孩子(DeleteObject当时).如果您不执行任何这些操作,则会违反参照约束,EF会在您调用时抛出异常SaveChanges- 臭名昭着的" 由于一个或多个外键属性不可为空而无法更改关系 "异常或类似.

    • 如果关系正在识别(因为主键的任何部分都不可能是必需的NULL),EF也会标记childEntityDeletedas.如果调用SaveChangesSQL DELETE语句将被发送到数据库.如果未违反数据库中的其他引用约束,则将删除该实体,否则将引发异常.

我实际上您链接的MSDN页面上的 " 备注"部分感到困惑,因为它说:" 如果关系具有参照完整性约束,则在依赖对象上调用Remove方法会标记关系和依赖对象以进行删除. ".这对我来说似乎是不准确甚至是错误的,因为上面的所有三种情况都有" 参照完整性约束 ",但只有在最后一种情况下才会删除子.(除非它们与" 依赖对象 " 意味着一个参与识别关系的对象,但这可能是一个不寻常的术语.)

  • @Mohammadreza:如果你将`NULL`解释为"Not a value"(而不是"值'NULL`",因为我有时写得有点草率)那么"可选关系"与参照完整性的定义并不矛盾. (3认同)
  • 参照完整性维基百科:参照完整性是数据的属性,当满足时,它要求关系(表)的一个属性(列)的每个值作为另一个(或相同)关系中的另一个属性的值存在(表) ),所以当关系是可选的时,我们会破坏数据完整性规则 (2认同)

Mat*_*ius 13

如果你真的想使用Deleted,你必须使你的外键可以为空,但是你最终会得到孤立的记录(这是你不应该首先做的那个主要原因之一).所以只需使用Remove()

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

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

值得注意的是,设置.State = EntityState.Deleted 不会触发自动检测到的更改. (档案)

  • 好吧,对于那些对我的回答进行投票的人来说,它与Slauma无关 - **他们都指向相同的文档**.我解释了现实生活中的例子,而他的理论部分则是如此 (4认同)