为什么nhibernate抱怨删除这个对象?

时间:2014-03-26 00:16:01

标签: c# nhibernate fluent-nhibernate-mapping

我有几个对象。

  1. 项目对象 - 这代表一个基本项目

  2. ProjectDependency 对象 - 这是将一个项目映射到另一个项目(依赖项目)的映射对象。请参阅nhibernate关系:

  3. 这是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]

    有人可以帮助澄清问题所在,以及我使用上述映射的方式是否不正确

3 个答案:

答案 0 :(得分: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将为您完成清理工作。

答案 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);

    }
}

希望这有帮助。

相关问题