2010-01-20 4 views
7

Je pense que les entités devraient mettre en œuvre l'égalité par rapport clé primaire par défaut, mais la documentation NHibernate recommande d'utiliser l'identité de l'entreprise:nhibernate: quelles sont les meilleures pratiques pour la mise en œuvre de l'égalité?

La façon la plus évidente est d'implémenter equals()/GetHashCode() en comparant la valeur d'identifiant des deux objets. Si la valeur est la même, les deux doivent être la même ligne de la base de données, ils sont donc égaux (si les deux sont ajoutés à un ISet, nous n'aurons qu'un seul élément dans l'ISet). Malheureusement, nous ne pouvons pas utiliser cette approche. NHibernate affectera uniquement des valeurs d'identifiant aux objets qui sont persistants, une instance nouvellement créée n'aura aucune valeur d'identifiant! Nous vous recommandons d'implémenter Equals() et GetHashCode() en utilisant l'égalité des clés métier.

méthode affaires égalité clé signifie que les equals() compare uniquement les propriétés qui forment la clé de l'entreprise, une clé qui identifierait notre instance dans le monde réel (une clé candidate naturelle)

Et l'exemple (également de la doc):

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

Ceci a obtenu ma tête tourner parce que la notion d'identité d'entreprise (selon l'exemple) est la même que la comparaison par la syntaxe, qui est essentiellement le type de sémantique I associe avec ValueObjects . La raison de ne pas utiliser les clés primaires de base de données comme valeurs de comparaison est que cela changera le hashcode de l'objet si la clé primaire n'est pas générée côté client (ex incremental) et que vous utilisez une sorte de collection hashtable (comme ISet) pour stocker vos entités.

Comment puis-je créer une bonne implémentation d'égalité qui ne brise pas les règles générales de l'égalité/hashcode (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) et qui est également conforme aux règles nhibernate?

+0

Pourquoi voulez-vous (spécifiquement)/devez-vous utiliser Equals? – apollodude217

Répondre

13

Ceci est un problème connu avec ORM. Ici, je décris les solutions que je connais et donne quelques conseils.

1 Surrogate/clé primaire: Comme vous le mentionnais généré automatiquement

, si l'objet n'a pas été enregistré, cela ne fonctionne pas.

2 Surrogate/clé primaire: valeur attribuée

Vous pouvez décider d'affecter la valeur du PK dans le code, ainsi que l'objet a toujours un ID et peut être utilisé à titre de comparaison. Voir Don't let hibernate steal your identity.

3 clé naturelle

Si l'objet est une autre clé naturelle, autre que la clé primaire, vous pouvez utiliser celui-ci. Ce serait le cas pour une entité cliente, qui a une clé primaire numérique et un numéro de client de chaîne. Le numéro de client identifie le client dans le monde réel et est une clé naturelle qui ne changera pas.

4 Object valeurs

En utilisant les valeurs d'objet pour l'égalité est possible. Mais avez-vous mentionné d'autres lacunes? Cela peut être problématique si les valeurs changent et que l'objet est dans une collection .Par exemple, si vous avez un Set avec deux objets qui étaient différents au début, mais ensuite vous changez les valeurs pendant qu'elles sont de référence dans l'ensemble afin qu'elles deviennent égales. Ensuite, vous brisez le contrat du Set. Voir Hibernate equals and hashcode.

5 mixtes: valeur + AutoGenerate clés primaires/ de substitution

Si les objets à comparer ont une carte d'identité déjà, l'utiliser. Sinon, utilisez les valeurs d'objet pour la comparaison.

Tous ont des avantages et des inconvénients. À mon humble avis, le meilleur est 3, si cela est possible avec votre modèle de domaine. Sinon, j'ai utilisé 5 et cela a fonctionné, bien qu'il y ait encore un piège lors de l'utilisation des collections. Je n'ai jamais utilisé 2 mais cela semble aussi une solution raisonnable, si vous trouvez un moyen de générer le PK dans le code. Peut-être que d'autres personnes ont des conseils pour celui-ci.

+0

Je ne vois pas opt 1 comme un problème si vous ne hachez pas vos entités avant de les persister (par exemple, n'utilisez pas les collections ISet). – Marius

+0

Nice un (+1) Félicitations –

Questions connexes