如何删除NHibernate中的子对象?

如何删除NHibernate中的子对象?,nhibernate,Nhibernate,我有一个父对象,它与子对象的IList有一对多的关系。删除子对象的最佳方式是什么?我没有删除父对象。我的父对象包含子对象的IList。以下是一对多关系的映射: <bag name="Tiers" cascade="all"> <key column="mismatch_id_no" /> <one-to-many class="TGR_BL.PromoTier,TGR_BL"/> </bag> 如果我尝试单独删除子对象,然后将其从父对象中

我有一个父对象,它与子对象的IList有一对多的关系。删除子对象的最佳方式是什么?我没有删除父对象。我的父对象包含子对象的IList。以下是一对多关系的映射:

<bag name="Tiers" cascade="all">
  <key column="mismatch_id_no" />
  <one-to-many class="TGR_BL.PromoTier,TGR_BL"/>
</bag>
如果我尝试单独删除子对象,然后将其从父对象中删除,则会出现异常:

deleted object would be re-saved by cascade
这是我第一次处理删除NHibernate中的子对象。我做错了什么


编辑:只是澄清一下-我并没有试图删除父对象,只是删除子对象。我已经在父母身上建立了一对多的关系。是否还需要在子对象映射上创建多对一关系?

在导致问题的列上的映射中设置Not Null=true。但我不确定确切的语法(抱歉)。

将级联属性值从“全部”更改为“全部删除孤立项”

尝试使用merge()而不是saveOrUpdate()。此外,请确保您的级联设置为“全部删除孤立项”,并且您的父子关系是可逆的(在父项上为“反向”=true,然后在子项中为“非空”=true的父id字段)。

您将收到第一个错误,因为从集合中删除项时,NHibernate的默认操作模式是简单地中断关联。在数据库中,NHibernate尝试将子行上的外键列设置为null。由于该列中不允许空值,SQL Server将引发错误。清除集合不一定会删除子对象,但一种方法是设置cascade=all delete orphan。这将通知NHibernate它应该删除新的孤立行,而不是设置外键列

出现第二个错误是因为在调用SaveOrUpdate NHibernate时,首先删除所有子对象。然后,因为两个关系都没有标记为反向,所以NHibernate还尝试将子表中的外键列设置为null。由于行已被删除,您将收到第二个错误。您需要在关系的一侧设置inverse=true来修复此问题。这通常在一个(主键或父键)端完成。如果不这样做,NHibernate将为关系的每一方进行适当的更新。不幸的是,运行两个更新并不合适


你应该始终将你的关系的一面标记为相反的一面。根据您的编码方式,您可能需要也可能不需要使用级联。如果您想在尝试使用Clear()时利用一次性删除,则需要定义级联。

在我们的示例中,我们有许多产品的类别,其中一个产品不可为空

您可以通过在刷新之前删除产品并将其从父级集合中删除来解决此问题,但我们仍在寻找更好的解决方案

product = pRepo.GetByID(newProduct.ProductID);
product.Category.Products.Remove(product);
pRepo.Delete(product);

希望它能有所帮助

根据Chuck的回答,我通过在父端映射中添加Inverse=true解决了我的问题:

Message有许多MessageSent要:

[HasMany(typeof(MessageSentTo), Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)]
public IList<MessageSentTo> MessageSendTos
{
    get { return m_MessageSendTo; }
    set { m_MessageSendTo = value; }
}
[HasMany(typeof(MessageSentTo),Cascade=ManyRelationCascadeEnum.alldeleteOrphant,Inverse=true]
公共IList MessageSendTos
{
获取{return m_MessageSendTo;}
设置{m_MessageSendTo=value;}
}

我正在使用Castle ActiveRecord。谢谢你,Chuck。

好的,我在子对象的映射中将列设置为not null=“true”。因此,我在子对象的IList上调用clear()方法,然后尝试SaveOrUpdate()。我仍然收到“无法将空值插入列”错误。我还做错了什么吗?错误是在哪个列上抛出的?如何删除模型中的子对象?我正在调用父对象中Ilist子对象的clear()方法。然后我在父对象上调用SaveOrUpdate()。尝试了这个。我仍然收到相同的异常。删除父对象时,all-delete-orphan将删除子对象。这与删除孩子没有任何关系,就像这家伙问的那样。只是澄清一下-我现在只在父对象上定义了关系。我尝试将该对象上的级联设置为“全部”和“全部删除孤立对象”,两次结果相同。你的意思是我也需要在子对象上定义多对一关系?在这种情况下,reverse=“true”是否属于父对象或子对象?它属于不包含外键的类。。。通常是父母。感谢你的解释,我又发现了一个相反的问题,看到这样的解释真的很有帮助。这真的帮助我解决了一个问题。谢谢。不过这需要另一个存储库。
[HasMany(typeof(MessageSentTo), Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)]
public IList<MessageSentTo> MessageSendTos
{
    get { return m_MessageSendTo; }
    set { m_MessageSendTo = value; }
}