我有一個父表與一個可選 1:1與子表的關係(父母可以存在沒有孩子,但反之亦然)。父表的自動生成的主鍵用作子的主鍵/外鍵。模擬Cascade.AllDeleteOrphan與一對一流利nHibernate
感謝一對夫婦很好的參考(this question和this 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;
}
傑米 - 感謝您的答覆。該確切的代碼不會執行工作,因爲我將NULL傳遞給'service.Delete()'。但是我想我知道你的意圖,並且我嘗試了一些變化(使用特定於兒童的存儲庫,正如你所提到的那樣)。由於我在父節點上有'Cascade.All()',試圖通過Child存儲庫刪除子節點,這就是'刪除的對象會被級聯節點重新保存'的錯誤信息。 – Brett