我首先使用 EF 代码。一个简单的模型:

  item { public int Id {set; get;},... ,ICollection<ItemImages> {set; get;} }

    itemImages {
         public int Id {set; get; },
         public int ItemId {set; get; }
          , ... ,
         public Item Item  {set; get; }
      }

ItemConfig:EntityTypeConfiguration<Item>
{
 //some config statement;
 //...
// mark child delete when parent delete: waterfall delete.
 HasRequired(rs => rs.ItemCat).WithMany(rs => rs.Items).HasForeignKey(rs => rs.ItemCatId).WillCascadeOnDelete(true);
}

当通过 Remove() 删除实体时,它会很好地删除项目和相关的子项(项目图像记录)。
_db.Item.Remove(DeleteThisObj);
_db.SaveChanges();

但是当将其标记为删除时:
_db.Entry(DeleteThisObj).State = EntityState.Deleted;
_db.SaveChanges();

得到错误:

最佳答案

如果你真的想使用 Deleted,你必须让你的外键可以为空,但是你最终会得到孤立的记录(这是你首先不应该这样做的主要原因之一)。所以只需使用 Remove()
ObjectContext.DeleteObject(entity) 在上下文中将实体标记为已删除。 (此后将删除EntityState。)如果事后调用SaveChanges,EF会将SQL DELETE语句发送到数据库。如果没有违反数据库中的引用约束,实体将被删除,否则抛出异常。

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

如果关系是可选的,即数据库中从子项到父项的外键允许 NULL 值,则此外键将设置为 null,如果您调用 SaveChanges,则 childEntity 的此 NULL 值将写入数据库(即删除两者之间的关系)。这发生在 SQL UPDATE 语句中。不发生 DELETE 语句。

如果需要关系(FK 不允许 NULL 值)并且关系没有识别(这意味着外键不是 child 的(复合)主键的一部分),您必须将 child 添加到另一个 parent 或者您必须明确删除子项(然后使用 DeleteObject)。如果您不执行其中任何一项操作,则会违反引用约束,EF 将在您调用 SaveChanges 时抛出异常 - 臭名昭著的“关系无法更改,因为一个或多个外键属性不可为空”异常或类似。

如果关系是标识性的(这是必需的,因为主键的任何部分都不能为 NULL)EF 也会将 childEntity 标记为已删除。如果您调用 SaveChanges,则会将 SQL DELETE 语句发送到数据库。如果没有违反数据库中的其他引用约束,实体将被删除,否则抛出异常。

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

关于c# - Entity Framework DbContext .Remove(obj) vs .Entry(obj).State = EntityState.Deleted,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24755739/

10-13 09:31