首先EF4代码 - 从db中删除父项时删除所有子项?

时间:2011-07-20 13:48:45

标签: c# .net asp.net-mvc ef-code-first

我有一个被安排到层次结构中的类,例如:

class TestContainer
{
... bla bla bla...
  public Virtual Item Items {get;set;}
}
Class Item
{
[Key]
public int ID {get;set;}
public string PropA {get;set;}
public string PropB {get;set;}



[InverseProperty("Parent")]
public virtual ICollection<Item> Children { get; set; }

[InverseProperty("Contents")]
public virtual Item Parent { get; set; }
}

所以,我有一个更新方法,允许用户上传一组更新的孩子。

我一开始并没有意识到,但删除我的容器TestContainer并没有删除这些项目。

好的,没问题吧?

我插入了以下功能(这可能非常难看,但我仍处于原型设计阶段)

   private void DeleteItems(TestContainer existingContainer)
        {

            //setup a flat list for deletion
            List<Item> trashCan = new List<Item>();
            //delete the old CI's from the database
            BuildDeletionList(existingContainer.Items, ref trashCan);

            foreach (Item item in trashCan)
            {
                context.Items.Remove(item);
            }
        }


        private void BuildDeletionList(ICollection<Item> items, ref List<Item> trashCan)
        {
            if (items != null)
            {
                foreach (Item item in items)
                {

                    BuildDeletionList(item, ref trashCan);
                }
            }

        }

        private void BuildDeletionList(Item item, ref List<Item> trashCan)
        {

            if (Item.Children != null)
            {
                foreach (Item child in Item.Children)
                {
                    BuildDeletionList(item, ref trashCan);
                }
            }
        item.Children.clear();
            trashCan.Add(item);
        }

这里的问题是,这会崩溃我的测试服务器,或者当我删除递归位(并且只删除父项 - 测试此时出现的问题)时,我收到以下错误

“保存未公开其关系的外键属性的实体时发生错误.EntityEntries属性将返回null,因为无法将单个实体标识为异常源。”

我怎样才能最好级联删除一个项目及其所有子项目,以便我在数据库中没有孤儿? (正如我现在所做的那样)

1 个答案:

答案 0 :(得分:8)

您可以在数据库的外键上启用Cascade delete,而不是使用EF删除实体及其后代。它比生成多个删除语句更有效。

修改

配置模型时需要添加WillCascadeOnDelete()

        modelBuilder.Entity<Item>().HasMany(i => i.Children)
            .WithOptional(i => i.Parent)
            .HasForeignKey(i => i.ParentId)
            .WillCascadeOnDelete();