2010-01-20 30 views
7

creo que las entidades deben aplicar la igualdad en comparación clave principal por defecto, pero la documentación nhibernate recomienda el uso de identidad de la empresa:nhibernate: ¿cuáles son las mejores prácticas para implementar la igualdad?

La manera más obvia es implementar equals()/GetHashCode() comparando el valor del identificador de ambos objetos. Si el valor es el mismo, ambos deben ser la misma fila de la base de datos, por lo tanto, son iguales (si ambos se agregan a un ISet, solo tendremos un elemento en el ISet). Desafortunadamente, no podemos usar ese enfoque. ¡NHibernate solo asignará valores de identificador a los objetos que son persistentes, una instancia recién creada no tendrá ningún valor de identificador! Recomendamos implementar Equals() y GetHashCode() usando Business Key Equity. significa

negocios igualdad clave que los Iguales() método compara sólo las propiedades que forman la clave de negocio, una clave que podría identificar nuestra instancia en el mundo real (una clave candidato natural)

Y el ejemplo (también 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; 
} 

Esto hizo que mi cabeza dando vueltas porque la noción de identidad de la empresa (de acuerdo con el ejemplo) es la misma que la comparación por la sintaxis, que es básicamente el tipo de semántica asocio con ValueObjects . El motivo por el que no se utilizan las claves primarias de la base de datos como valores de comparación es porque cambiará el código hash del objeto si la clave primaria no se genera en el lado del cliente (por ejemplo, incremental) y utiliza algún tipo de colección hashtable (como ISet) para almacenar tus entidades

¿Cómo puedo crear una buena implementación de igualdad que no rompa las reglas generales de igualdad/código hash (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) y se ajuste a las reglas de nhibernate también?

+0

¿Por qué (específicamente) quiere/necesita utilizar Equals? – apollodude217

Respuesta

13

Este es un problema conocido con ORM. Aquí describo las soluciones que conozco y le doy algunos consejos.

1 Sustituto/clave principal: auto-generada

Como mencionado, si el objeto no se ha guardado, esto no funciona.

2 Sustituto/clave principal: valor asignado

Puede decidir asignar el valor del PK en el código, de esta manera el objeto tiene siempre una identificación y se puede utilizar para la comparación. Ver Don't let hibernate steal your identity.

3 Natural clave

Si el objeto tiene otra clave natural, que no sea la clave principal, puede utilizar éste. Este sería el caso para una entidad cliente, que tiene una clave principal numérica y, un número de cliente de cadena. El número de cliente identifica al cliente en el mundo real y es una clave natural que no cambiará. valora

4 Objeto

Usando los valores de objeto por la igualdad es posible. Pero tiene otras deficiencias que ha mencionado. Esto puede ser problemático si los valores cambian y el objeto está en una colección .Por ejemplo, si tiene un Set con dos objetos que eran diferentes al principio, pero luego cambia los valores mientras son referencia en el conjunto para que se vuelvan iguales. Luego rompes el contrato del Set. Ver Hibernate equals and hashcode.

5 mixtas: valor + Autogenerar primarias/claves suplentes

Si los objetos a comparar tener un ID ya, lo utilizan. De lo contrario, use los valores del objeto para la comparación.

Todos tienen algunos pros y contras. En mi humilde opinión, el mejor es 3, si es posible con su modelo de dominio. De lo contrario, he usado 5 y funcionó, aunque todavía hay alguna trampa al usar colecciones. Nunca usé 2, pero eso también suena como una solución sensata, si encuentras una forma de generar PK en el código. Tal vez otras personas tienen consejos para este.

+0

No veo la opción 1 como un problema si no hasch sus entidades antes de persistirlas (por ejemplo, no use colecciones de ISet). – Marius

+0

Nice one (+1) Felicitaciones –

Cuestiones relacionadas