我有几个对象。
项目对象 - 这代表一个基本项目
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 :(得分:2)
出于本答案的目的,我假设Project.ProjectDependencies
是ProjectDependency.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
集合中级联删除,因此projectA
和dep1
都会被删除。 projectB
留在数据库中。
好的,让我们重置一下。让我们从数据库中的projectA
,projectB
和dep1
重新开始。另外,让我们添加以下内容:
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
开始,我们如何找到dep2
和projectC
来清理它们?
两个选项:
session.Query<ProjectDependency>().Where(x => x.Dependent == projectA)
,然后手动清理关系。Project
:HasMany(x => x.DependentProjects)
.KeyColumn("DependentProjectId")
.AsBag()
.Inverse()
.Cascade.AllDeleteOrphan();
...然后NHibernate将为您完成清理工作。
答案 1 :(得分:1)
我假设关系是多对多关系而ProjectDependency是一个代表连接表的实体,很难从你的问题中判断出来。我假设桌子:
项目(ProjectId)
ProjectDependency(ProjectId,DependentProjectId),外键返回Project
要删除项目记录,您必须删除引用它的任何ProjectDependency记录。这意味着删除ProjectDependency.ProjectId引用Project的ProjectDependency记录和ProjectDependency.DependentProjectId引用的那些记录。要在代码中执行此操作,您只需从集合中删除引用的实体即可。由于您正在使用存储库模式,因此应在Delete方法
中实现此操作public void Delete(Project project)
{
using (var txn = _session.BeginTransaction())
{
project.ProjectDependencies.Clear();
project.DependentDependentOf.Clear();
_session.Delete(project);
txn.Commit();
}
}
答案 2 :(得分:1)
在下面的两个方法调用中显示一些代码会有所帮助:
Repository.Delete(project);
Repository.Commit();
但这是我的2美分,
从.Inverse()
ProjectDependencies
映射中移除HasMany
。
如果您希望nhibernate在“一对多”关系中从“一”侧管理状态,则不应在.Inverse()
映射中使用HasMany
。
所以它变成了这样:
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);
}
}
希望这有帮助。