7

エンティティはデフォルトで主キー比較による等価性を実装する必要があると思いますが、nhibernate のドキュメントではビジネス ID の使用が推奨されています。

最も明白な方法は、両方のオブジェクトの識別子の値を比較して Equals()/GetHashCode() を実装することです。値が同じである場合、両方とも同じデータベース行である必要があるため、それらは等しいです (両方が ISet に追加された場合、ISet には 1 つの要素しかありません)。残念ながら、そのアプローチを使用することはできません。NHibernate は永続的なオブジェクトにのみ識別子の値を割り当てます。新しく作成されたインスタンスには識別子の値はありません! ビジネス キーの等価性を使用して、Equals() と GetHashCode() を実装することをお勧めします。

ビジネス キーの等価性とは、Equals() メソッドがビジネス キーを形成するプロパティのみを比較することを意味します。これは、現実世界でインスタンスを識別するキー (自然な候補キー) です。

そして例(これもドキュメントから):

public override bool Equals(object other)
{
    if (this == other) return true;

    Cat cat = other as Cat;
    if (cat == null) return false; // null or not a cat

    if (Name != cat.Name) return false;
    if (!Birthday.Equals(cat.Birthday)) return false;

    return true;
}

ビジネス ID の概念 (例によると) は構文による比較と同じであり、これは基本的に ValueObjects に関連付けるタイプのセマンティクスであるため、これには頭が回転します。データベースの主キーを比較値として使用しない理由は、クライアント側で主キーが生成されず (インクリメンタルなど)、何らかのハッシュテーブル コレクション (ISet など) を使用する場合、オブジェクトのハッシュコードが変更されるためです。エンティティを保存するため。

equality/hashcode ( http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx ) の一般的なルールに違反せず、nhibernate ルールにも準拠する優れた等価実装を作成するにはどうすればよいですか?

4

1 に答える 1

13

これは ORM の既知の問題です。ここでは、私が知っている解決策の概要を説明し、いくつかの指針を示します。

1 サロゲート/主キー: 自動生成

あなたが言及したように、オブジェクトが保存されていない場合、これは機能しません。

2 サロゲート/主キー: 割り当てられた値

コードで PK の値を割り当てることを決定できます。これにより、オブジェクトは常に ID を持ち、比較に使用できます。休止状態に ID を盗ませないでください を参照してください。

3 ナチュラルキー

オブジェクトに主キー以外の別の自然キーがある場合は、これを使用できます。これは、数値の主キー文字列のクライアント番号を持つクライアント エンティティの場合です。クライアント番号は、現実世界でクライアントを識別するものであり、変化しない自然キーです。

4 オブジェクト値

同等のオブジェクト値を使用することは可能です。しかし、あなたが言及した他の欠点があります。値が変更され、オブジェクトがコレクション内にある場合、これは問題になる可能性があります。たとえば、Set最初は異なっていた 2 つのオブジェクトを持つ があり、それらがセット内で参照されている間に値を変更して、それらが等しくなるようにした場合です。次に、の契約を破りますSetHibernate equals と hashcodeを参照してください。

5 混合: 値 + 主キー/代理キーの自動生成

比較するオブジェクトに既に ID がある場合は、それを使用します。それ以外の場合は、オブジェクトの値を比較に使用してください。

すべてに長所と短所があります。私見、ドメインモデルで可能な場合、最高は3です。それ以外の場合は、コレクションを使用するときにまだいくつかのトラップがありますが、5 を使用して動作しました。私は 2 を使用したことはありませんが、コードで PK を生成する方法が見つかれば、それも賢明な解決策のように思えます。たぶん、他の人がこれについての指針を持っています。

于 2010-01-20T10:07:49.470 に答える