Nhibernate 删除父级和子级而不进行级联

Nhibernate 删除父级和子级而不进行级联,nhibernate,parent-child,Nhibernate,Parent Child,我的代码正在累积用户的对象删除和更新,然后尝试一次应用它们。在我遇到问题的情况下,业务要求只有在没有子项的情况下才删除父项,但必须手动删除子项 我可以用以下代码重现该问题: 映射: 实体: 公共类SomeClass { 公共虚拟整数ID{get;set;} 公共虚拟字符串名称{get;set;} 公共虚拟父对象{get;set;} } 公共类父类 { 公共虚拟整数ID{get;set;} 公共虚拟字符串名称{get;set;} 公共虚拟ISet子项{get;set;} } 节目: 使用(v

我的代码正在累积用户的对象删除和更新,然后尝试一次应用它们。在我遇到问题的情况下,业务要求只有在没有子项的情况下才删除父项,但必须手动删除子项

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

映射:

实体:
公共类SomeClass
{
公共虚拟整数ID{get;set;}
公共虚拟字符串名称{get;set;}
公共虚拟父对象{get;set;}
}
公共类父类
{
公共虚拟整数ID{get;set;}
公共虚拟字符串名称{get;set;}
公共虚拟ISet子项{get;set;}
}
节目:
使用(var sessionFactory=cfg.BuildSessionFactory())
使用(var session=sessionFactory.OpenSession())
{
var p=新的SomeParent();
var obj=newsomeclass(){Parent=p};
session.Save(p);
session.Save(obj);
session.Flush();
}
使用(var sessionFactory=cfg.BuildSessionFactory())
使用(var session=sessionFactory.OpenSession())
使用(var tx=session.BeginTransaction())
{
foreach(会话中的var p.CreateCriteria().List())
{
删除(p);
}
foreach(会话中的var p.CreateCriteria().List())
{
删除(p);
}
session.Flush();
tx.Commit();
}
当我交换两个
Delete()
循环时,这个例子就起作用了。在我的应用程序中,我不能随意影响用户按下删除按钮的顺序

如果我将
cascade=“delete”
添加到
one-to-many
映射中,此示例也会起作用。这违反了业务要求,即当父母仍有子女时,不能删除他们

我本以为NHibernate会帮我处理这个订单。尤其是在地图中已经有了所有必要的信息。我只是做错了什么,还是必须“手动”对删除进行正确排序,以便NHibernate对其进行检查


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

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

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

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


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

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

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

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


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

在某种程度上,这种期望源于一个简单的事实,即NHibernate可以这样做,其他ORM也可以这样做。手动实现排序只是一个不切实际的最后解决方案。还有什么其他的orm可以做到这一点呢?如果反转设置在子对象映射上,NH的行为如何?即使NH可以做到这一点,它是否满足了您的要求,即所有仅与无子对象关联的父对象都可以被删除?此外,我执行删除操作。在某种程度上,这种期望植根于一个简单的事实,即NHibernate可以做到这一点,而其他orm也可以做到这一点。手动实现排序只是一个不切实际的最后解决方案。还有什么其他的orm可以做到这一点呢?如果反转设置在子对象映射上,NH的行为如何?即使NH可以做到这一点,它是否满足了您的要求,即所有仅与无子对象关联的父对象都可以被删除?此外,我执行删除操作。它们只是以错误的顺序提交到数据库。
<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();
}