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

标签 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();

最佳答案

根据我的研究,在当前版本的 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/

相关文章:

asp.net-mvc - StructureMap、NHibernate 和多个数据库

nhibernate - 使用Spring和Hibernate在两个数据库实例中使用声明式事务管理

c# - 在没有 HBM 文件的情况下设置 NHibernate/LINQ 的最快和最简单的方法

c# - POCO 对象中的非空约束

nhibernate - NHibernate。按功能排序

c# - NHibernate 4 升级的重大变化

c# - NHibernate:如何设置连接超时

c# - 使用 nhibernate 检索单个行和列并将其转换为字符串

.net - 添加到 Nhibernate 集合而不初始化集合

asp.net - Web API ASP.NET 中的 NHibernate : No session bound to the current context