2014-03-26 58 views
3

我有幾個對象。爲什麼nhibernate抱怨刪除這個對象?

  1. 項目對象 - 這代表了一個基本項目

  2. ProjectDependency對象 - 這是映射對象的一個​​項目映射到另一個項目(依賴項目)。見NHibernate的關係:

這裏是ProjectDependencies映射類:

public class ProjectDependencyMap 
    { 
     public ProjectDependencyMap() 
     { 
     References(x => x.Project).Not.Nullable().Fetch.Join(); 
     References(x =>.DependencyProject).Not.Nullable().Column("DependencyProjectId").Fetch.Join(); 
    } 
} 

,這裏是該項目映射文件:

public class ProjectMap 
{ 
    public ProjectMap() 
    { 
     HasMany(x => x.ProjectDependencies).AsBag().Inverse().Cascade.AllDeleteOrphan().Fetch.Select().BatchSize(80); 

     HasMany(x => x.ProjectDependentOf).KeyColumn("DependentProjectId").AsBag().Inverse().Cascade.AllDeleteOrphan().Fetch.Select().BatchSize(80); 

    } 
} 

通常能正常工作,但有時當我去刪除項目使用:

var project = Model.GetProject(id); 
Repository.Delete(project); 
Repository.Commit() 

我得到這個錯誤:

刪除的對象將被重新保存通過級聯(移除協會刪除的對象)ProjectDependency#324]

有人能幫助澄清這一問題就在這裏,如果什麼方式我使用上面的映射是不正確的

+0

Try:'References(x => x.Project).Not.Nullable()。Fetch.Join()。LazyLoad();' – George

+0

@George =這似乎沒有區別 – leora

回答

2

爲了這個答案的目的,我假設Project.ProjectDependenciesProjectDependency.Project關係的另一端,而不是ProjectDependency.Dependent關係。 (現在說的3倍快)

考慮以下對象:

var projectA = new Project(); 
var projectB = new Project(); 
var dep1 = new ProjectDependency 
{ 
    Project = projectA, 
    Dependent = projectB 
}; 
projectA.ProjectDependencies.Add(dep1); 

...,並將它們保存到數據庫中。現在,讓我們刪除一個。

session.Delete(projectA); 

一切工作正常。 NHibernate級聯刪除整個ProjectDependencies集合,所以projectAdep1都被刪除。 projectB留在數據庫中。好的,讓我們重新設置吧。讓我們從數據庫中的projectAprojectBdep1開始。此外,讓我們添加下列內容:

var projectC = new Project(); 
var dep2 = new ProjectDependency 
{ 
    Project = projectC, 
    Dependent = projectA 
}; 
projectC.ProjectDependencies.Add(dep2); 

當我們現在刪除projectA會發生什麼?

session.Delete(projectA); 

一切都按照以前那樣繼續進行。級聯將刪除dep1。然而,沒有什麼可以清理dep2,因此錯誤。 dep2仍有對projectA的引用,我們試圖刪除它。

錯誤消息提示的解決方案是在嘗試刪除實體之前清理這些關係。但是,你打算怎麼做?從projectA開始,我們如何找到dep2projectC來清理它們?

兩個選項:

  • 執行查詢:session.Query<ProjectDependency>().Where(x => x.Dependent == projectA),然後手動清理的關係。
  • 添加另一個集合Project
HasMany(x => x.DependentProjects) 
    .KeyColumn("DependentProjectId") 
    .AsBag() 
    .Inverse() 
    .Cascade.AllDeleteOrphan(); 

...然後NHibernate的會照顧清理的爲您服務。

+0

感謝Daniel。我實際上已經有你最後的建議(見更新的問題),我有這個ProjectDependentOf屬性。我之前沒有收錄它,因爲我不認爲它是重要的,但現在我已經添加了它。 。請指教。你也可以清楚你的意思是「手動清理關係」 – leora

+0

另一個問題是,我沒有看到任何其他項目有依賴項目(如你的例子),所以它不清楚什麼是試圖堅持到參考 – leora

+0

對我的問題在評論中的任何想法? – leora

1

我假設關係是多對多的,而ProjectDependency是一個表示連接表的實體,很難從你的問題中知道。我假設表:

項目(專案編號)

ProjectDependency(專案編號,DependentProjectId)與外鍵返回項目

要刪除項目的記錄,你必須刪除所有引用它的任何ProjectDependency記錄。這意味着刪除項目由ProjectDependency.ProjectId引用的ProjectDependency記錄和由ProjectDependency.DependentProjectId引用的項目。要在代碼中執行此操作,只需從集合中刪除引用的實體即可。由於您使用存儲庫模式,此操作應在刪除方法

public void Delete(Project project) 
{ 
    using (var txn = _session.BeginTransaction()) 
    { 
     project.ProjectDependencies.Clear(); 
     project.DependentDependentOf.Clear(); 
     _session.Delete(project); 
     txn.Commit(); 
    } 
} 
+0

雖然nhibernate會爲我做這個,因爲我已經在Cascase.DeleteOrphan的問題中列出了映射嗎? – leora

1

顯示兩種方法中的一些代碼來實現以下稱會幫助:

Repository.Delete(project); 
Repository.Commit(); 

但這裏是我的2美分,

ProjectDependenciesHasMany映射中刪除.Inverse()。 如果您希望nhibernate從「一對多」關係中的「一方」管理狀態,則不應在HasMany映射中使用.Inverse()

所以變成這樣:

public class ProjectMap 
{ 
    public ProjectMap() 
    { 
     HasMany(x => x.ProjectDependencies).AsBag().Cascade.AllDeleteOrphan().Fetch.Select().BatchSize(80); 

     HasMany(x => x.ProjectDependentOf).KeyColumn("DependentProjectId").AsBag().Inverse().Cascade.AllDeleteOrphan().Fetch.Select().BatchSize(80); 

    } 
} 

希望這有助於。

相關問題