2014-03-26 60 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); 

    } 
} 

希望这有助于。

相关问题