从集合

时间:2017-06-29 23:47:46

标签: entity-framework asp.net-mvc-5

我有以下代码从父母那里删除子女和孙子女

        MyEntities dbContext = new MyEntities();

        var parent = dbContext.Parents
            .Include(x => x.Childrens.Select(y => y.GrandChildrens))
            .Where(x => x.ParentID == 1)
            .SingleOrDefault();

        // get first child
        var child = parent.Childrens.First();

        // remove all grand childrens from child
        var count = child.GrandChildrens.Count;
        for (int i = 0; i < count; i++)
        {
            child.GrandChildrens.Remove(child.GrandChildrens.ElementAt(0));
        }

        // remove child from parent
        parent.Childrens.Remove(child);            

        // save changes
        dbContext.SaveChanges();

以上代码抛出异常

  

操作失败:无法更改关系,因为   一个或多个外键属性是不可为空的。当一个   改变了关系,相关的外键属性是   设置为空值。如果外键不支持空值,   必须定义新的关系,外键属性必须是   分配了另一个非空值,或者不相关的对象必须是   删除。

经过几篇文章后,似乎我必须将Entity的状态标记为已删除,而不是从集合中删除实体。

        MyEntities dbContext = new MyEntities();

        var parent = dbContext.Parents
            .Include(x => x.Childrens.Select(y => y.GrandChildrens))
            .Where(x => x.ParentID == 1)
            .SingleOrDefault();

        // get first child
        var child = parent.Childrens.First();

        // remove all grand childrens from child
        var count = child.GrandChildrens.Count;
        for (int i = 0; i < count; i++)
        {
            dbContext.Entry<GrandChild>(child.GrandChildrens.ElementAt(0)).State = EntityState.Deleted;
        }

        // remove child from parent
        dbContext.Entry<Child>(child).State = EntityState.Deleted;

        // save changes
        dbContext.SaveChanges();

上面的代码

但我有疑问

1&GT;如何启用级联删除,以便我不必显式删除GrandChildrens?我正在使用DB第一种方法。

2 - ;如果我们将实体添加到集合中并调用dbContext.SaveChanges(),那么EF会保存新添加的实体,即使我们没有明确地将实体的状态标记为Added。为什么删除操作不适用?为什么我们必须将实体的状态明确设置为Deleted

2 个答案:

答案 0 :(得分:1)

啊,我一直在ORM之间蹦蹦跳跳......我更喜欢NHibernate的其余原因之一,已经有了关于级联删除孤儿的回复,这些反应不在EF6中,但显然可以在EF Core中使用并期待EF7 ......

EF6需要将实体标记为已删除,因为它仍然缺少孤立跟踪的概念。 :(

的略微冗长的变体
   var child = parent.Childrens.First();

   child.GrandChidrens.ToList().ForEach(x=>dbContext.Entity(x).State = EntityState.Deleted);
   dbContext.Entity(child).State = EntityState.Deleted;
   parent.Childrens.Remove(child); 

你可以试试EF Core,虽然它有很多其他的龙......

答案 1 :(得分:0)

  1. 当您在ChildrenGrandchildren之间声明外键关系时,您可以设置删除规则。您可以在SQL Management Studio中执行此操作。只需选择 Cascade 即可。现在,当您删除父表中的记录时,SQL Server将删除子表中的所有相关记录。

  2. 我只能猜测。如果您不需要删除记录,但只想破坏关系怎么办?你会用什么方法?方法ICollection.Remove看起来像个好人。所以这只是EF作者的选择。