1

我有一個父表與一個可選 1:1與子表的關係(父母可以存在沒有孩子,但反之亦然)。父表的自動生成的主鍵用作子的主鍵/外鍵。模擬Cascade.AllDeleteOrphan與一對一流利nHibernate

感謝一對夫婦很好的參考(this questionthis site),我能夠得到一個工作的1:1關係映射出來。按照預期,我可以創建帶或不帶孩子的家長,更新一個或兩個家長,並刪除父級聯以刪除孩子。

不過,我想我的HasOne映射結構內以某種方式「模擬」一HasMany映射Cascade.AllDeleteOrphan()選項,這樣如果關係的孩子最終被刪除,子表中相應的行會被刪除時,父對象被保存。因爲,如果我嘗試手動刪除孩子,我可以理解得到一個'deleted object would be re-saved by cascade'錯誤消息。

有沒有人找到一個好辦法做到這一點,但仍然只使用HasOne映射?我想要做的甚至是1:1的關係,還是應該使用一對多,並依靠我的數據庫約束和業務邏輯來防止多個孩子?

簡化代碼:

// Parent class 
public partial class Parent 
{ 
    public int pkParentID { get; set; } 
    public Child child { get; set; } 
    public Parent() { } 
} 

// Child class 
public partial class Child 
{ 
    public int pkParentID {get; set; } 
    public Parent parent { get; set; } 
    public Child() { } 
    public Child(Parent parent) { this.parent = parent; } 
} 

// Parent mapping 
public class ParentMap : ClassMap<Parent> 
{ 
    public ParentMap() 
    { 
     Table(@"Parent"); 
     LazyLoad(); 
     Id(x => x.pkParentID) 
      .Column("pkProjectID") 
      .Not.Nullable() 
      .GeneratedBy.Identity(); 
     HasOne<Child>(x => x.Child) 
      .PropertyRef(r => r.Parent) 
      .Cascade.All(); 
    } 
} 

// Child map 
public class ChildMap :ClassMap<Child> 
{ 
    public ChildMap() 
    { 
      Table(@"Child"); 
      LazyLoad(); 
      Id(x => x.pkParentID, "pkParentID") 
      .GeneratedBy.Foreign("Parent"); 
      HasOne<Parent>(x => x.Parent) 
      .Constrained() 
      .ForeignKey() 
      .Cascade.None(); 
    } 
} 


// Ideally, the code snippet below would remove the row from the Child table 
Parent parent = service.GetById(uniqueID); 
if (parent.Child != null) 
    parent.Child = null; 
service.SaveOrUpdate(parent); 


// Just in case, here's my repository code 
public virtual void SaveOrUpdate(T entity) 
{ 
    ISession _session = NHibernateSessionProvider.GetSession(); 
    if (!_session.Transaction.IsActive) 
    { 
     using (ITransaction transaction = _session.BeginTransaction()) 
     { 
      try 
      { 
       _session.SaveOrUpdate(entity); 
       transaction.Commit(); 
      } 
      catch 
      { 
       transaction.Rollback(); 
      } 
     } 
    } 
} 

編輯::我也曾嘗試下面的代碼片段,這就是給我的錯誤消息「被刪除的對象將通過級聯重新保存」。

... 
Parent parent = parentService.GetById(uniqueID); 
if (parent.Child != null) 
{ 
    childService.Remove(parent.Child); // this gives the above error 
    parent.Child = null; 
} 

回答

0

cascade setting all-delete-orphan沒有在NHibernate中實現,請參閱NH-1262。在對該問題發表評論時有拉取請求,所以可能會在未來的版本中發佈。

現在你可以這樣做:

Parent parent = service.GetById(uniqueID); 
parent.Child = null; 
service.Delete(parent.Child); // probably needs to occur in a different repository 
// commit transaction or flush session, there's no need to call SaveOrUpdate 
+0

傑米 - 感謝您的答覆。該確切的代碼不會執行工作,因爲我將NULL傳遞給'service.Delete()'。但是我想我知道你的意圖,並且我嘗試了一些變化(使用特定於兒童的存儲庫,正如你所提到的那樣)。由於我在父節點上有'Cascade.All()',試圖通過Child存儲庫刪除子節點,這就是'刪除的對象會被級聯節點重新保存'的錯誤信息。 – Brett