【问题标题】:NHibernate performing a delete with Cascade.All causes N+1 deletesNHibernate 使用 Cascade 执行删除。所有导致 N+1 删除
【发布时间】:2013-03-21 10:08:06
【问题描述】:

我有两个实体 Password 和 PasswordHash。 Password 有一组 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();

【问题讨论】:

  • 你能给出导致 N+1 删除的代码吗?
  • 我猜这个,你用来执行删除的代码,可能会感兴趣:nhforge.org/doc/nh/en/…
  • 使用 HQL 删除子项(第一次),然后删除父项?您还使用哪个数据库供应商?
  • BTW ReferencedBy 是什么(抱歉有任何愚蠢的问题)?当它为 PropertyRef 改变时,它会改变什么吗?
  • 对不起,我忘了这是我们的扩展方法。它只是将 KeyColumn 设置为适当的值。

标签: nhibernate


【解决方案1】:

根据我的研究,在当前版本的 NHibernate (3.3) 中,似乎无法在您的域上使用 password.hashes.Clear()session.Delete(password) 等操作删除带有单个 DELETE 语句的子集合对象。 NHibernate 文档引用了one shot deletes,但对于单向或双向一对多关联,我无法通过逆向和级联的任何组合来完成这项工作。

另一种方法是使用on-delete="cascade",它会禁用NHibernate 中的级联功能并将其留给数据库来强制级联删除。更多信息可以在thisnh users google group讨论中找到。

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();
}

【讨论】:

    猜你喜欢
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    相关资源
    最近更新 更多