C# 使用Nhibernate删除父项后删除多对多表中的所有记录

C# 使用Nhibernate删除父项后删除多对多表中的所有记录,c#,sql-server,nhibernate,C#,Sql Server,Nhibernate,请帮我解决以下情况。我有三张表格名片,联系人和多对多表格名片。在删除Cardlist中的记录时,我想删除多对多表ContactCardlist中的所有记录。因此,我找到所需的Cardlist,使用foreach通过“ContactCardList”进行迭代—设置并使用session.Delete(ItemFromTheSet)删除每个记录。但在transaction.commit()之后,我得到了一个异常,该异常表示我们不能将列CardlistId(在表ContactCardlist中)更新为N

请帮我解决以下情况。我有三张表格名片,联系人和多对多表格名片。在删除Cardlist中的记录时,我想删除多对多表ContactCardlist中的所有记录。因此,我找到所需的Cardlist,使用foreach通过“ContactCardList”进行迭代—设置并使用session.Delete(ItemFromTheSet)删除每个记录。但在transaction.commit()之后,我得到了一个异常,该异常表示我们不能将列CardlistId(在表ContactCardlist中)更新为NULL。所以使用了“更新”命令,而不是“删除”命令

在下面,您可以找到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>

..//大量的财产

提前谢谢大家。

我不熟悉NHibernate,但您是否考虑过:

(a) 在CardList和ContactCardlist之间设置OnDelete的级联关系(如果可能),并在ContactCardlist中的外键上设置索引以确保效率

(b) 使用原始ADO删除带有“从ContactCardlist中删除,其中Cardlistid=X”的记录

方案(a)简单有效。选项(b)比项目迭代更有效


这两种方法都可行,但选项(a)可确保相关关系总是在不做任何进一步工作的情况下被删除。

您所经历的是来自NHibernate ISession的本质

  • 我们确实加载了“父”
    卡片列表
    ,因此当前的
    会话
    知道这个对象,甚至知道它的子对象
  • 我们迭代子项并询问
    会话。删除(子项)
    (ItemFromTheSet)
  • 最后调用
    session.Flush()
    ,NHibernates必须决定必须执行哪些SQL语句
  • 映射到父对象的所有子对象都将被删除。从上面的映射中,NHibernate了解到,它们必须首先从
    集合中删除
  • 将发布更新,将父级
    更改为空
  • 所以,事情就是这样。我们如何解决这个问题?首先,我们必须通知NHibernate,孩子完全了解自己的父母,并且能够自我管理。这就是
    inverse=“true”
    设置

    <set name = "contactcardlists" inverse="true"
         cascade="none"  order-by="ContactId">
      <key column ="cardlistid"/>
      <one-to-many class="ContactCardlist" />
    </set>  
    
    NHibernate将正确发布DELETE语句。这种情况下的映射应类似于:

    <set name = "contactcardlists" inverse="true"
         cascade="all-delete-orphan"  
         order-by="ContactId">
      <key column ="cardlistid"/>
      <one-to-many class="ContactCardlist" />
    </set>  
    
    
    
    最后,如果您可以将代理密钥引入到配对表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>
    
    
    

    使用具有代理密钥的对象时。。。更简单

    很抱歉,还有一个问题:据我所知,我们可以在集合的描述中添加inverse=“true”,并在foreach语句中使用Delete方法(而不将属性“cascade”从“None”更改为“all Delete orphan”)?你说的是“下一个改进”,所以据我所知,这不是一个强制性的改变。相反的=“true”(你应该用谷歌搜索它,以获得更多信息),意思是:NHibernate,这个集合是由能够照顾自己的元素构建的。如果一切都设置正确,这意味着,一旦此项从集合中删除,NHibernate将直接与此项通信:删除。没有逆。。。NHibernate不能确定,必须先更新。。。从child中删除引用,然后删除…如果有帮助,那就太好了。享受NHibernate。。。这是一个很棒的工具;)
    <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>