nhibernate fluent-nhibernate nhibernate-mapping

La unión opcional NHibernate genera inserción en lugar de actualización



fluent nhibernate mapping (2)

Pude hacer que el código funcionara mediante el mapeo de una función que apunta a la identificación en el componente:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.NH2876" default-lazy="false"> <class name="Customer"> <id name="Id"> <generator class="guid" /> </id> <property name="Name" column="Name" /> <join table="CustomerData" optional="true"> <key column="CustomerId" unique="true" /> <component name="ExtendedData"> <property name="CustomerId" formula="[CustomerId]" insert="false" update="false" /> <property name="SomeData" /> </component> </join> </class>

Esto también requiere que la propiedad CustomerId se agregue a la clase de componente.

La razón por la que esto sucede es que cuando NHibernate extrae el registro existente, no rellena el componente relacionado si no hay valores no nulos. Por lo tanto, cuando comprueba los "valores antiguos" al llamar a UpdateOrInsert en AbstractEntityPersister, ve solo un objeto nulo para el atributo del componente y, por lo tanto, piensa que es un inserto. Este es el mismo comportamiento cuando no hay ningún registro en la tabla. Al agregar el campo de fórmula asignada usando el campo clave, el atributo del componente tiene un valor en los "campos antiguos" y sabe correctamente que necesita realizar una actualización.

Aquí hay un informe con las pruebas de unidades adicionales y la solución de trabajo (para ser utilizado con el proyecto NHibernate.Test) en base a las pruebas de unidades originales que se encuentran aquí: https://nhibernate.jira.com/browse/NH-2876 :

https://github.com/kfehribach/NH2876

Kent

Actualmente estamos utilizando NHibernate para admitir un modelo de entidad flexible. Los campos del sistema se almacenan en una tabla y los campos dinámicos se almacenan en una tabla de extensión. Las tablas compartían las mismas claves principales.

Usamos un componente JOIN para mapear un diccionario en la tabla de extensiones. El componente JOIN se asigna como opcional pero se produce el siguiente error:

  1. Crea una nueva entidad sin atributos dinámicos. Hibernate almacena un registro vacío en la segunda tabla: todas las columnas se almacenan como nulas excepto por la clave externa / primaria.

  2. Cargue el registro creado y establezca un campo dinámico.

  3. Guardar el registro actualizado dará como resultado un error. NHibernate emitirá una nueva inserción en lugar de una declaración de actualización.

Actualmente hay un error en Nhibernate que puede estar relacionado con esto: https://nhibernate.jira.com/browse/NH-2876 .

Me pregunto si actualmente hay una solución para este error NHibernate Core o si alguien tiene una solución alternativa a esto.

¡Gracias!


Pocas líneas sobre la asignación dinámica de columnas se pueden encontrar aquí: NHibernate Dynamic Columns Number . Y realmente en este escenario, este podría ser el camino.

<join table="ElemntValues" > <key column="ElementId" /> <dynamic-component> ...

Pero, sinceramente, terminé con una solución un poco diferente.

Así que esta es mi entidad C # (por ejemplo, contacto) con algunos campos MuchMore

IDictionary _muchMore; // se the property name ... used later for mapping public virtual IDictionary MuchMore { get { return _muchMore?? (_muchMore= new Hashtable()); } set { _muchMore= value; } }

Ahora, hay una cantidad imposible de mapear posibilidades con NHibernate

4.4. Modelos dinámicos

Las entidades persistentes no necesariamente tienen que estar representadas como clases POCO en el tiempo de ejecución. NHibernate también admite modelos dinámicos (utilizando Diccionarios de diccionarios en tiempo de ejecución). Con este enfoque, no se escriben clases persistentes, solo se asignan los archivos.

...

Primero, en el archivo de mapeo, se debe declarar un entity-name lugar de (o además de) un nombre de clase

Eso es genial. Porque ahora podemos crear un mapeo virtual de la marca de la entidad ContactMuchMore, que repetirá la tabla unida:

<class entity-name="ContactMuchMore" table="Contact_MuchMore_table" dynamic-insert="true" dynamic-update="true" batch-size="25" > <id name="ID" column="Contact_ID" type="int"> <generator class="foreign"> <param name="property">Parent</param> </generator> </id> <one-to-one name="Parent" class="Contact" constrained="true" />

Increíble ... nosotros con NHibenrate tenemos una entidad mapeada - virtual. Tiene dependencia de contacto ... por lo que podemos usar el contacto real como generador de ID y mapeo one-to-one

Y aquí está el mapeo Contact.cs :

<class name="Contact" ... > ... // here we mapp the property name // to our virtual entity <one-to-one name="MuchMore" entity-name="ContactMuchMore" cascade="all" />

Hay algunos lados oscuros de uno a uno (ambas tablas siempre se cargan) pero podrían resolverse con proyecciones. Con Cascade All, no hay problemas con los valores persistentes en ninguna de estas tablas (contact o contact_hasmore).

Mi respuesta es describir el mapeo xml (no fluido). Pero supongo que si el concepto es claro, podemos usar cosas similares en forma fluida o, excepcionalmente, usar xml.