2

PasswordとPasswordHashの2つのエンティティがあります。PasswordにはPasswordHashesのコレクションがあります(これらは異なるマスクのハッシュです)。

パスワードを削除するとき、関連するすべてのPasswordHashも削除したいと思います。

私は次のようにマッピングを行いました:

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

2つのクエリが生成されることを期待していました。

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

1 に答える 1

2

私の調査によると、NHibernate(3.3)の現在のリリースでは、ドメインオブジェクトなどDELETEのアクションを使用して、単一のステートメントで子コレクションを削除することはできないようです。NHibernateのドキュメントでは、ワンショットの削除について言及していますが、単方向または双方向の1対多の関連付けに対して、逆とカスケードの任意の組み合わせでこの作業を行うことはできませんでした。password.hashes.Clear()session.Delete(password)

1つの代替方法はon-delete="cascade"、NHibernateのカスケード機能を無効にし、データベースに任せてカスケード削除を強制するを使用することです。詳細については、このnhユーザーのGoogleグループディスカッションをご覧ください。

コメントセクションでRippoが言及している他のオプションは、HQLを使用することです。2つのステートメントが必要になるため、それらをトランザクションでラップするのが最適です。

using (var transaction = session.BeginTransaction()
{
   session.Query("delete from PasswordHash h where h.Password = :password")
                   .SetParameter("password", password)
                   .ExecuteUpdate();
   session.Delete(password);
   transaction.Commit();
}
于 2013-03-21T23:23:18.487 に答える