代码之家  ›  专栏  ›  技术社区  ›  Tigraine

NHibernate树删除

  •  3
  • Tigraine  · 技术社区  · 14 年前

    我正在努力解决一个小问题,并开始得出结论,这根本不可能。

    我有一张叫“组”的桌子。与大多数这些系统组一样,组具有ParentGroup和Children集合。因此,表组如下所示:

    Group
      -ID (PK)
      -Name
      -ParentId (FK)
    

    我使用fnh automappings进行了映射,但我必须覆盖默认值:

    p.References(x => x.Parent)
        .Column("ParentId")
        .Cascade.All();
    p.HasMany(x => x.Children)
        .KeyColumn("ParentId")
        .ForeignKeyCascadeOnDelete()
        .Cascade.AllDeleteOrphan()
        .Inverse();
    

    现在,一般的想法是能够删除一个节点,它的所有子节点也可以被NH删除。所以删除唯一的根节点应该基本上清除整个表。

    我先试过 Cascade.AllDeleteOrphan 但这只适用于从子集合中删除项,而不适用于父集合的删除。

    接下来我尝试 ForeignKeyCascadeOnDelete 因此操作通过 on delete cascade . 但一旦我这样做了,MSSQL2008就不允许我创建这个约束,因为:

    引入外键约束 'FKBA21C18E87B9D9F7'表'Group' 可能导致循环或多重级联 路径。删除时指定不执行任何操作或 更新时不执行任何操作,或修改其他 外键约束。

    好吧,这就是我想要的。我想我只需要循环遍历这些子元素,然后逐个删除它们,这样做就得到了一个n+1。如果有人对如何更优雅地做到这一点提出建议,我会迫不及待地去听听。

    1 回复  |  直到 11 年前
        1
  •  1
  •   Peter Alexandr Nikitin    11 年前

    我是这样做的,而且效果很好。

        public class Node_Map : ClassMap<Node>
        {
            public Node_Map()
            {
                References(x => x.Parent, "IdCmsNodeParent");
                HasMany(x => x.Childs).AsBag()
                                      .Inverse()
                                      .Cascade.Delete()
                                      .KeyColumn("IdNodeParent");
            }
        }
    

    但是,如果NHibernate删除它,你会得到N+1。只有正确的数据库约束才能一次删除它。

    如果您希望在SQL Server 2008中高效地执行此操作,那么应该使用递归CTE。

    检查: