同じ問題が発生しています...一意の制約を含むテーブルにマップされたコレクションを持つエンティティがあります。
私が理解していないのは、Stuarts の回答によると、コレクションの挿入の前にコレクションの削除が発生する必要があるということですか? NHibernate のソースコードを調べてみると、メソッドに次CollectionUpdateAction
のコードを含むクラスが見つかりました。Execute
persister.DeleteRows(collection, id, session);
persister.UpdateRows(collection, id, session);
persister.InsertRows(collection, id, session);
次に、挿入の前に削除が実行されると思いますが、明らかにそうではありません。このシナリオでは CollectionUpdateAction は使用されませんか? CollectionUpdateAction はいつ使用されますか?
答え:
私はこれを次のように回避しました:
- 私のマッピングでは、cascade オプションを「all-delete-orphan」ではなく「delete-orphan」に設定しました
データベースへのアクセスはすべてリポジトリ経由で行われます。リポジトリの save メソッドには、エンティティ用に次のコードがあります。
public void Save( Order orderObj )
{
// Only starts a transaction when there is no transaction
// associated yet with the session
With.Transaction(session, delegate()
{
session.SaveOrUpdate (orderObj);
session.Flush();
foreach( OrderLine line in orderObj.Lines )
{
session.SaveOrUpdate (line);
}
};
}
そこで、orderObj を保存します。カスケードが delete-orphan に設定されているため、削除されるオブジェクトはデータベースから削除されます。
を呼び出した後SaveOrUpdate
、データベースへの変更を確実にフラッシュする必要があります。
delete-orphan カスケード設定により、OrderLine が挿入または更新されないようにするため、コレクションをループして、OrderLine ごとに「SaveOrUpdate」を呼び出す必要があります。これにより、新しい OrderLines が確実に挿入され、変更されたものが更新されます。変更されていない OrderLine に対しては何も実行されません。
これは理想的な解決策ではありませんが (見苦しいハックです)、ある程度は機能し、リポジトリの背後で抽象化されているため、これが今のところこの問題に対処する方法です...