2010-06-05 52 views
3

我正在努力解決一個小問題,並開始得出結論,這根本是不可能的。我有一個叫做組的表。與大多數這些系統一樣,Group有一個ParentGroup和一個Children集合。所以表集團看起來是這樣的:NHibernate刪除樹

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,但是它僅適用於刪除Children集合中的項目,而不是刪除父項目。

接下來我試着ForeignKeyCascadeOnDelete,所以操作通過on delete cascade委託給數據庫。但是,一旦我這樣做,MSSql2008不允許我創建這個約束,以失敗:

表「集團」 引進國外KEY約束 「FKBA21C18E87B9D9F7」可能會導致循環或多個級聯 路徑。指定ON DELETE NO ACTION或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY約束。

那麼,這就是我的。我想我會循環通過孩子並逐個刪除它們,從而做一個N + 1。如果任何人有關於如何做得更優雅的建議,我會非常樂意聽到它。

回答

1

我這樣做,它的工作。

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。

檢查:

+0

但是這樣你不使用相同的列兒童和家長? 你最終2 FK列: IdCmsNodeParent和IdNodeParent 應該可以只用一個.. 無論如何,感謝您的鏈接! – Tigraine 2010-06-05 20:12:50

+0

呃,對不起。 IdCmsNodeParent應該是IdNodeParent。我複製粘貼我的代碼,我想刪除單詞「Cms」,因爲它沒有任何信息,但我忘記在參考方法中刪除它。 – dmonlord 2010-06-06 09:50:25

+0

很酷。非常感謝。我會嘗試的 – Tigraine 2010-06-06 11:57:58