请帮我解决以下情况。我有三张桌子Cardlist,Contact和多对多表ContactCardlist。我想在删除Cardlist中的记录时删除多对多表ContactCardlist中的所有记录。所以,我找到了所需的Cardlist,使用foreach迭代“contactcardlists”-set并使用session.Delete(ItemFromTheSet)删除每条记录。但是在transaction.commit()之后,我获得了一个异常,它说我们不能用NULL更新列CardlistId(在表ContactCardlist中)。因此使用“更新”命令,而不是“删除”一个。
您可以在下面找到表Cardlist和ContactCardlist的映射。
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="XXXXX.Entities" assembly="XXXXX">
<class name="ContactCardlist" table="ContactCardlist">
<composite-id class="ContactsCardlistId" name="ContactsCardlistId" unsaved-value="any" >
<key-many-to-one name="cardlist" class="Cardlist" column="CardlistId" />
<key-many-to-one name="contact" class="Contact" column="ContactId" />
</composite-id>
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="XXXXXXXXX.Entities" assembly="XXXXXXXXXXXXXX">
<class name="Cardlist" table="Cardlist">
<id name="cardlistid" column="cardlistid" type="int">
<generator class="native"/>
</id>
....//lots of properties
<set name = "contactcardlists" cascade="none" order-by="ContactId">
<key column ="cardlistid"/>
<one-to-many class="ContactCardlist" />
</set>
</class>
</hibernate-mapping>
提前谢谢大家。
答案 0 :(得分:2)
您所遇到的是来自NHibernate ISession的本质。
Cardlist
,因此当前session
知道此对象,甚至是其子级session.Delete(child)
(ItemFromTheSet) session.Flush()
,NHibernates必须决定必须执行哪些SQL语句<set name = "contactcardlists">
集合中删除它们。 <key column ="cardlistid"/>
变为空所以,这就是发生的事情。我们怎么解决呢?首先,我们必须通知NHibernate,孩子完全了解其父母,并且可以自我管理。这是inverse="true"
设置
<set name = "contactcardlists" inverse="true"
cascade="none" order-by="ContactId">
<key column ="cardlistid"/>
<one-to-many class="ContactCardlist" />
</set>
这将指示NHibernate直接处理child,并仅发出DELETE语句。
级联可能是下一个改进。因为那样我们就可以打电话了
parent.contactcardlists.Clear()
session.Udpate(parent)
和NHibernate会发出相关的DELETE语句。在这种情况下的映射应该是:
<set name = "contactcardlists" inverse="true"
cascade="all-delete-orphan"
order-by="ContactId">
<key column ="cardlistid"/>
<one-to-many class="ContactCardlist" />
</set>
最后,如果您可以将Surrogated密钥引入配对表ContactCardlist - ContactCardlistId,那么很多东西都会被简化。真的很多。然后孩子的映射可能是:
<class name="ContactCardlist" table="ContactCardlist">
<id column="ContactsCardlistId" name="Id" />
<many-to-one name="cardlist" class="Cardlist" column="CardlistId" />
<many-to-one name="contact" class="Contact" column="ContactId" />
</class>
使用具有Surrogated键的对象...更容易
答案 1 :(得分:1)
我不熟悉NHibernate,但您考虑过:
(a)在CardList和ContactCardlist之间为OnDelete建立级联关系(如果可能),并在ContactCardlist中设置外键索引以确保效率。
OR
(b)使用原始ADO删除带有“DELETE FROM ContactCardlist WHERE Cardlistid = X”的记录。
选项(a)简单有效。选项(b)比项目迭代更有效。
要么可以工作,但选项(a)确保始终删除相关关系而无需任何进一步的工作。