我有两个实体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();
最佳答案
根据我的研究,在当前版本的 NHibernate (3.3) 中,似乎无法使用 password 等操作通过单个
或 DELETE
语句删除子集合。您的域对象上的 hashes.Clear()session.Delete(password)
。 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();
}
关于NHibernate 使用 Cascade.All 执行删除会导致 N+1 删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15544507/