【问题标题】:How to set cascade on self-referencing relations?如何在自引用关系上设置级联?
【发布时间】:2013-09-09 15:45:00
【问题描述】:

我有默认方案,您有 Category 本身、RootCategoryChildCategories。如何指定我的流利模型构建器在删除时级联所有子类别?

型号

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Category RootCategory { get; set; }
    public virtual ICollection<Category> ChildCategories { get; set; }
    public virtual ICollection<Item> Items { get; set; }
}

我尝试过的

我曾尝试使用流畅的模型构建器,但是当我尝试更新数据库时,这个会出错。

引入 FOREIGN KEY 约束 表上的“FK_dbo.Categories_dbo.Categories_RootCategory_Id” “类别”可能会导致循环或多个级联路径。指定开 DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Category>().HasOptional(x => x.RootCategory).WithMany(x => x.ChildCategories).WillCascadeOnDelete(true);
}

【问题讨论】:

    标签: c# asp.net-mvc entity-framework asp.net-mvc-4 entity-framework-5


    【解决方案1】:

    我遇到了同样的问题。关于流畅的API配置,我不知道你是否可以在那里完成。您可以做的是将 WillCascadeOnDelete 设置为 false,然后自己删除 ChildCategories。

    private void DeleteChildCategories(Category category) 
    {
        foreach (Category subCategory in category.ChildCategories.ToList())
            {
                if (subCategory.SubCategories.Count() > 0)
                {
                    DeleteChildCategories(subCategory);
                }
                else
                {
                    _db.Category.Remove(subCategory);
                }
            }
        _db.Category.Remove(category);
    }
    

    然后,您可以在控制器操作中删除类别时调用 DeleteChildCategories。

    DeleteChildCategories(Category);
    _db.SaveChanges();
    

    希望这会有所帮助。

    标记

    【讨论】:

    • 我遇到了与 OP 类似的问题,这可能是我最终会使用的解决方案。
    • 根据this,您不能在自引用表上使用级联删除,无论是使用 EF 还是纯 T-SQL。我遇到了同样的问题,并且最终导致代码中的递归删除效率低下。
    【解决方案2】:

    您似乎对类别和子类别使用相同的模型。没关系,但是当您尝试激活级联删除时,您会收到无限循环,因为它不知道要删除什么。

    我认为,您的模型中需要 parentCategoryID 属性。在这种情况下,您将拥有牢固的关系,并且级联删除应该可以工作。

    已编辑: 我的意思是,如果你有parentCategoryID,你可以尝试如下修改你的代码:

    modelBuilder.Entity<Category>().HasOptional(x => x.RootCategory).WithMany(x => x.ChildCategories).HasForeignKey(x => x.parentCategoryID).WillCascadeOnDelete(true);
    

    【讨论】:

    • 暴露 Parent_Id 将如何解决问题? EF 使用的数据库中已经有 Parent_Id。
    【解决方案3】:

    我记得我遇到过类似的问题。我希望这会有所帮助:

    我有一个评论实体,它可以回复(其他评论),创建评论的“无限树”。

    每个评论都有自己的 CommentID(主键)和 ParentID(外键,无 CASCADE)。然后我的评论表上有一个数据库触发器:

    CREATE TRIGGER [dbo].[Trigger_DeleteChildComments]
    ON [dbo].[Comment]
    FOR DELETE
    AS
    BEGIN
        SET NoCount ON
        DELETE FROM Comment WHERE ParentID IN (SELECT CommentID FROM DELETED)
    END
    

    (或者:“删除评论c后,删除所有其他以c为父级的cmet。)

    请注意,这仅适用于我的业务逻辑不允许此评论图上的“循环”,确保该图保持为树。因此,我相信我的触发器不会导致无限循环。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多