我首先使用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);
}
当通过删除()删除实体时,它会很好地删除项目和相关子项(项目图像记录)。
_db.Item.Remove(DeleteThisObj);
_db.SaveChanges();
但是当标记为删除时:
_db.Entry(DeleteThisObj).State = EntityState.Deleted;
_db.SaveChanges();
得到错误:
操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
答案 0 :(得分:14)
如果你真的想使用Deleted,你必须让你的外键可以为空,但是你最终会得到孤立的记录(这是你不应该做的主要原因之一)首先要这样做)。所以只需使用Remove()
ObjectContext.DeleteObject(entity)在上下文中将实体标记为已删除。 (之后它的EntityState被删除。)如果之后调用SaveChanges,EF会向数据库发送一个SQL DELETE语句。如果违反了数据库中的引用约束,则将删除该实体,否则将引发异常。
EntityCollection.Remove(childEntity)将parent和childEntity之间的关系标记为已删除。如果从数据库中删除了childEntity本身,并且在调用SaveChanges时究竟发生了什么,取决于两者之间的关系类型:
如果关系是可选的,即从子级引用到数据库中的父级的外键允许NULL值,则此外部将设置为null,如果调用SaveChanges,则将为childEntity写入此NULL值数据库(即两者之间的关系被删除)。使用SQL UPDATE语句会发生这种情况。没有DELETE语句。
如果需要关系(FK不允许NULL值)并且关系未识别(这意味着外键不是子组件(复合)主键的一部分)您必须要将子项添加到另一个父项,或者必须显式删除子项(然后使用DeleteObject)。如果你不做这些中的任何一个,就会违反参考约束,当你调用SaveChanges时,EF会抛出一个异常 - 臭名昭着的&#34;由于一个或多个外键属性是,所以关系无法改变。不可为空&#34;例外或类似。
如果关系正在识别(因为主键的任何部分都不能为NULL,则必然需要),EF也会将childEntity标记为已删除。如果调用SaveChanges,则会将SQL DELETE语句发送到数据库。如果数据库中没有违反其他参照约束,则将删除该实体,否则将引发异常。
值得注意的是设置.State = EntityState.Deleted
does not trigger automatically detected change.