【问题标题】:EF4 Code first - delete all children when deleting parent from db?EF4 代码优先 - 从数据库中删除父级时删除所有子级?
【发布时间】:2011-07-20 13:48:45
【问题描述】:

我有一个按层次结构排列的类,例如:

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,因为无法将单个实体标识为异常源。”

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

【问题讨论】:

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


    【解决方案1】:

    您可以在数据库的外键上启用Cascade delete,而不是使用 EF 删除实体及其后继者。这比生成多个删除语句要高效得多。

    编辑

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

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

    【讨论】:

    • 谢谢 :) 无论如何,添加适当的 [ForeignKey] 标签等使我的原始模型正常工作,而在删除每个之前,显然使开发服务器崩溃的不是 .clear() 内容垃圾桶的附加项目。不过我会使用级联,谢谢!
    • Err... 你究竟是如何启用级联删除的?是否可以通过注解或仅使用 fluent API 来实现?
    • 看起来不错,但遗憾的是我认为它不适用于同一张桌子。从好的方面来说,这正是您拥有多表父/子时需要做的事情。我会将其标记为答案,希望这将满足大多数人的需求。
    • @Yablargo 是的,你是对的。您需要删除 FK 并在 DatabaseInitializer 中使用 cascade delete 手动创建它
    猜你喜欢
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多