visual tutorial studio framework español c# nhibernate orm nhibernate-mapping

c# - tutorial - nhibernate visual studio 2017



Manera mínima y correcta de mapear uno a muchos con NHibernate (2)

Debería agregar la cascada all-delete-orphan en la relación one-to-many , si elimina al Employee la dirección también se eliminará.

Si no necesita la referencia del Employee cree una relación inverse=false como esta: aquí

Soy nuevo en NHibernate y C #, así que sea amable.

Tengo las siguientes dos entidades NHibernate:

Employee { private long _id; private String _name; private String _empNumber; private IList<Address> _addresses; //Properties... }

y

Address { private long _id; private String _addrLine1; private String _addrLine2; private String _city; private String _country; private String _postalCode; //Properties }

y tienen una relación one-to-many de Employee a Address (cada empleado puede tener múltiples direcciones en su registro) . Convenientemente ignorando el hecho de que más de un empleado puede residir en la misma dirección.

Entiendo esto desde la perspectiva de los objetos en la memoria (las entidades NHibernate). Lo que estoy luchando con los archivos de mapeo (y estoy tomando un ejemplo fácil aquí). Esto es lo que he propuesto hasta ahora:

// Intentionally left out XML and <hibernate-mapping> // Mappings for class ''Employee''. --> <class name="Employee" table="Employees"> <id name="ID"> <generator class="native"> </id> <property name="Name" /> <property name="EmpNumber" /> <bag name="Addresses"> <key column="AddressId" /> <one-to-many class="Address" /> </bag> </class>

y

// Intentionally left out XML and <hibernate-mapping> . // Mappings for class ''Address'' <class name="Address" table="Addresses"> <id name="ID"> <generator class="native"> </id> // Intentionally left out name="Employee" // as I don''t have corresponding field in Address entity. <many-to-one class="Employee" column="EmployeeID" cascade="all" /> <property name="AddrLine1" /> <property name="AddrLine2" /> <property name="City" /> <property name="Country" /> <property name="PostalCode" /> </class>

  1. ¿Es esto correcto?
  2. Si no, parece que lo que me falta aquí es un campo en la entidad de Address que es una referencia a la entidad Employee correspondiente. Pero si es así, entonces no puedo entender por qué es necesario: no necesito obtener una Address de un Employee , solo al revés ...

Solo algunos consejos, resumiendo los estándares más adecuados que descubrí al trabajar con NHibernate.

1) Si hay una referencia bidireccional en persitence (columna DB) , explíquela también en código C# bidireccional .

En otras palabras, si un niño tiene referencia a uno de los padres , el padre debe hacer referencia al niño .

public class Employee { ... public virtual IList<Address> { get; set; } } public class Address { ... public virtual Employee Employee { get; set; } }

Esto representa el Dominio empresarial tal como es. La dirección pertenece al empleado y el empleado pertenece a la dirección.

Si por alguna razón realmente queremos restringir eso, deberíamos protected modificador, pero aun así mantener la referencia en C#

2) Use inverse="true" . Esto podría usarse solo si mapeamos ambos lados (como se indicó anteriormente), y conducirá a más "esperados y optimizados" INSERTAR y ACTUALIZAR escrituras

Leer más aquí:

inverso = ejemplo "verdadero" y explicación por mkyong

3) Use el mapeo de búsqueda por lotes casi en cualquier parte. Eso evitará problemas de 1 + N durante la consulta. Lee mas:

algunos detalles sobre la búsqueda de lotes

4) En caso de que ese único objeto (in our case Employee) sea root (el otro no tiene tanto sentido sin él) - use cascada. Lee mas:

nhibernate - Crear hijo actualizando padre, o crear explícitamente?

Reglas 2,3,4 en un fragmento de mapa:

<class name="Employee" ... batch-size="25"> ... <bag name="Addresses" lazy="true" inverse="true" batch-size="25" cascade="all-delete-orphan" > // wrong! This columns is the same as for many-to-one //<key column="AddressId" /> // it is the one column expressing the relation <key column="EmployeeId" /> <one-to-many class="Address" /> </bag> <class name="Address" ... batch-size="25"> ... <many-to-one not-null="true" name="Employee" column="EmployeeID" />

3) si usamos inverse="true , no olvide asignar ambos lados de relación (mayormente crítico durante la creación)

La razón es:

instruimos a NHibernate - el otro lado ( Address ) es responsable de la relación persistente. Pero para hacerlo correctamente, esa Address necesita tener referencia a Employee : para poder mantener su ID en su columna en la tabla de direcciones.

Así que este debería ser el código estándar para crear una nueva dirección

Employee employee = ... // load or create new Address address = new Address { ... Employee = employee, // this is important }; Employee.Addresses.Add(address); session.SaveOrUpdate(employee); // cascade will trigger the rest

También podemos introducir algún método como AddAddress() que ocultará esta complejidad, pero establecer ambas partes es una buena práctica.