La realidad es más complicada. Cuando carga la entidad usando session.Load
o accede a una propiedad que está cargada de modo perezoso, NHibernate devuelve un objeto proxy. Ese objeto proxy estará hidratado (los datos se cargarán de DB) cuando acceda a cualquiera de sus propiedades por primera vez. Para lograr esto, NHibernate genera una clase de proxy que extiende la clase de entidad y anula todos los captadores y definidores de propiedades. Esto funciona perfectamente cuando no se utiliza la herencia, ya que no tendrá forma de diferenciar entre proxy y clase de entidad (clase base de proxy), p. prueba simple proxy is MyEntity
siempre funcionará.
Ahora imaginemos que tenemos una entidad Persona:
class Person {
// lazy-loaded
public Animal Pet { get; set; }
}
y también tenemos Animal
jerarquía de clases:
public abstract class Animal { ... }
public class Cat { ... }
public class Dog { ... }
Supongamos ahora que Pet
propiedad es cargado ligeramente, cuando se pide NHibernate para la persona pet obtendrá un objeto proxy:
var pet = somePerson.Pet; // pet will be a proxy
Pero dado que Pet
es una propiedad con carga lenta, NH no sabrá si será una instancia de Cat
o Dog
, por lo que hará todo lo posible y creará un proxy que se extiende a Animal
. El proxy pasará la prueba para pet is Animal
pero fallará las pruebas para pet is Cat
o pet is Dog
.
Supongamos ahora que tendrá acceso a alguna propiedad del objeto pet
, lo que obligará a NH a cargar datos de DB. Ahora NH sabrá que su mascota es, por ejemplo, a Cat
pero el proxy ya está generado y no se puede cambiar. Esto obligará a NHibernate a emitir una advertencia de que el proxy original para pet
que se extiende tipo Animal
se reducirá al tipo Cat
. Esto significa que a partir de ahora el objeto proxy para animal con pet.Id
que cree utilizando session.Load<Animal>(pet.Id)
extenderá Cat
a partir de ahora. Esto también significa que dado que Cat
ahora se almacena como parte de la sesión, si cargamos una segunda persona que comparte cat con la primera, NH utilizará la instancia de proxy Cat
ya disponible para poblar la propiedad de carga lenta.
Una de las consecuencias será que la referencia de objeto a pet
será diferente a la referencia obtenida por session.Load<Animal>(pet.Id)
(en object.ReferencesEqual
sentido).
Ahora, cuando esto puede causar daño a usted:
Cuando se pone sus entidades en Set
s o Dictionary
IES en su código o si utiliza cualquier otra estructura que requiere Equals/GetHashCode
par a trabajar . Esto se puede solucionar fácilmente, proporcionando a medida Equals/GetHashCode
aplicación (ver: http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=1)
Cuando intenta emitir su objeto proxy para apuntar tipo, por ejemplo, (Cat)pet
, pero de nuevo no se conocen soluciones (por ejemplo Getting proxies of the correct type in NHibernate)
Así que la moraleja es evitar lo más posible la herencia en su modelo de dominio.
¿Es esto un gran problema? ¿Qué pasa si ignoramos esta ADVERTENCIA? – Beatles1692
Ser un gran negocio o no depende del nivel de riesgo que está dispuesto a aceptar. Como siempre habrá una desconexión entre su código y su base de datos, no siempre se puede asegurar que el casting funcionará. Esto dará lugar a errores que pueden ser difíciles de diagnosticar y que pueden no resolverse sin cambios en la base de datos o el código. – Fourth