多对多和HQL批量删除

时间:2011-02-26 20:53:43

标签: nhibernate hql nhibernate-mapping

我有两个实体,它们之间定义了多对多关系。

<set name="TreasuryCodes" table="ServiceProviderAccountTreasuryCode" lazy="true" cascade="all">
  <key column="ServiceProviderAccountId" />
  <many-to-many column="TreasuryCodeId" class="TreasuryCode" />
</set>

<set name="ServiceProviderAccounts" table="ServiceProviderAccountTreasuryCode" lazy="true" inverse="true" cascade="all">
  <key column="TreasuryCodeId" />
  <many-to-many column="ServiceProviderAccountId" class="ServiceProviderAccount" />
</set>

现在我想通过ServiceProviderId删除所有ServiceProviderAccounts。我写这段代码:

    public void DeleteAllAccount(int serviceProviderId)
    {
        const string query = "delete ServiceProviderAccount spa where spa.ServiceProvider.Id = :serviceProviderId";
        repository.Session.CreateQuery(query)
            .SetInt32("serviceProviderId", serviceProviderId)
            .ExecuteUpdate();
        repository.Session.Flush();
    }

我收到了这个例外:

Test method Test.ServiceRepositoryTest.DeleteAllAccountTest threw exception: 
NHibernate.Exceptions.GenericADOException: could not execute update query[SQL: delete from ServiceProviderAccount where ServiceProviderId=?] ---> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FKBC88A84CB684BF79". The conflict occurred in database "Test", table "dbo.ServiceProviderAccountTreasuryCode", column 'ServiceProviderAccountId'.
The statement has been terminated.

我很困惑,因为我已经在实体上定义了cascade,不应该nhibernate从ServiceProviderAccountTreasuryCode中删除行吗?

更新


好吧,看起来像ExecuteUpdate不是在寻找NHibernate级联,可能是因为它在删除之前没有加载实体?无论如何还有其他方法从ServiceProviderAccountTreasuryCode表中删除,然后通过HQL从ServiceProviderAccounts中删除吗?我知道我可以在数据库上使用级联,但我想避免这种情况。我想要的是通过HQl从多对多关联表中删除行。可能吗?或者我应该使用纯SQL?

2 个答案:

答案 0 :(得分:3)

看起来你有一个参照完整性问题,即一个foregin密钥关系,你要删除的id正被引用到其他地方,并且该表最终不会引用任何内容。如果那是你想要做的,那么你可以运行截断命令,但我不知道你为什么会这样做..

我建议你做一个正常的删除,即使用nhibernate会话和Linq,如下所示:

 foreach(var sessionProvider in Session.Linq<ServiceProviderAccount >().Where(x=>x.ServiceProvider.Id==servinceProviderId))
       Session.Delete(sessionProvider);

现在请注意,这并不是一个糟糕的删除方式,因为它们不会立即触发dB并且是会话的一部分,直到您的事务被提交,如果定义了映射,这应该处理您的参照完整性问题crrectly。

希望这有效..

答案 1 :(得分:0)

看起来它不服从级联。用于更新/删除的HQL批处理操作相对较新,并且或多或少地直接转换为SQL。我相信你也必须跟踪相关的表格。

如果您只删除单个实体,那么批量删除对您没有多大帮助。为了让NHibernate实际考虑级联,它必须加载实际的权限,而不是你的例子。

我问了一个类似的问题,我得到的答案可能会让你感兴趣

Remove entity in NHibernate only by primary key