NHibernate使用Cascade.All执行删除导致N + 1删除

时间:2013-03-21 10:08:06

标签: nhibernate

我有两个实体Password和PasswordHash。密码有一组PasswordHashes(这些是具有不同掩码的哈希)。

当我删除密码时,我希望删除所有相关的PasswordHash。

我做了这样的映射:

mapping.HasMany(x => x.PasswordHashes)
            .Cascade
            .All()
            .Inverse()
            .ReferencedBy(x => x.Password);

我希望生成两个查询:

DELETE FROM "PasswordHash" WHERE "IdPassword" = :p0

显然

DELETE FROM "Password" WHERE "IdPassword" = :p0

相反,NHibernate生成了N + 1个查询:

DELETE FROM "PasswordHash" WHERE "IdPasswordHash" = :p0 (N)

DELETE FROM "Password" WHERE "IdPassword" = :p0 (1)

如何将此行为更改为更优化?

编辑:删除的代码:

session.Delete(password);
session.Flush();

1 个答案:

答案 0 :(得分:2)

根据我的研究,在当前版本的NHibernate(3.3)中,看起来不可能使用DELETE或{{password.hashes.Clear()之类的操作删除具有单个session.Delete(password)语句的子集合。 1}}在您的域对象上。 NHibernate文档引用one shot deletes但是我无法使用逆向和级联的任何组合来实现单向或双向一对多关联。

另一种方法是使用on-delete="cascade"来禁用NHibernate中的级联功能,并将其留给数据库以强制执行级联删除。有关详细信息,请参阅this nh用户google小组讨论。

Rippo在评论部分提到的另一个选项是使用HQL。您需要两个语句,因此最好将它们包装在一个事务中,即

using (var transaction = session.BeginTransaction()
{
   session.Query("delete from PasswordHash h where h.Password = :password")
                   .SetParameter("password", password)
                   .ExecuteUpdate();
   session.Delete(password);
   transaction.Commit();
}