删除没有级联的父级和子级

时间:2011-08-17 11:11:21

标签: nhibernate parent-child

我的代码正在累积来自用户的对象删除和更新,然后尝试一次性应用这些对象。在遇到麻烦的情况下,只有在没有孩子的情况下才会删除父母,但是必须手动删除子女,这是业务要求。

我可以使用以下代码重现该问题:

映射:

<class name="SomeClass" >
  <id name="ID">
    <generator class="native" />
  </id>
  <property name="Name" />
  <many-to-one name="Parent" not-null="true" />
</class>

<class name="SomeParent" >
  <id name="ID">
    <generator class="native" />
  </id>
  <property name="Name" />
  <set name="Children" batch-size="100" inverse="true">
    <key column="Parent" not-null="true" />
    <one-to-many class="SomeClass" />
  </set>
</class>

实体:

public class SomeClass
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual SomeParent Parent { get; set; }
}

public class SomeParent
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual ISet<SomeClass> Children { get; set; }
}

程序:

using (var sessionFactory = cfg.BuildSessionFactory())
using (var session = sessionFactory.OpenSession())
{
    var p = new SomeParent();
    var obj = new SomeClass() { Parent = p };
    session.Save(p);
    session.Save(obj);
    session.Flush();
}

using (var sessionFactory = cfg.BuildSessionFactory())
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
    foreach (var p in session.CreateCriteria<SomeParent>().List<SomeParent>())
    {
        session.Delete(p);
    }

    foreach (var p in session.CreateCriteria<SomeClass>().List<SomeClass>())
    {
        session.Delete(p);
    }

    session.Flush();
    tx.Commit();
}

当我交换两个Delete()循环时,此示例有效。在我的应用程序中,我没有能够影响用户按下删除按钮的顺序。

如果我将cascade="delete"添加到one-to-many映射,则此示例也有效。这违反了父母在有孩子的情况下无法删除的业务要求。

我原本希望NHibernate为我处理这个订单。特别是因为映射中已经提供了所有必要的信息。我只是做错了什么,还是我必须“手动”对删除进行正确排序,以便NHibernate能够理解它们?

我正在使用NHibernate 3.2.0GA(从nuget构建3.2.0.4000)。

1 个答案:

答案 0 :(得分:1)

我不明白你期望NHibernate应该能够处理这种情况。由于您没有指定级联设置,因此您必须自己处理删除。

我的建议是跟踪集合中的删除,并且在验证数据之前不要发出NHibernate Deletes。也就是说,为父对象和子对象创建MarkForDeletion方法。当用户单击“删除”时,这些方法会将对象添加到集合中。

当用户准备好提交事务时,循环遍历已标记为删除的子对象,将其从父级的子集合中删除,并将其对父对象的引用设置为null。然后遍历标记为删除的父对象,并验证其子集合是否为空。

如果数据有效,则可以删除父对象,并让级联设置(全部或全部删除 - 孤立)处理子记录。