Mapeos polimórficos o heterogéneos

Hay veces que uno cree que sus ideas son irrealizables y esta semana tenía que implementar un mapeo con NHibernate que creía que no iba a ser algo fácil.

Pero entonces he dado con el elemento <any> y <many-to-any>. He llegado a ellos casi por casualidad, simplemente porque me ha picado la curiosidad al ver eso de “any” (en contraposición a “many”) y he tirado del hilo vía Google.

En la documentación de NHibernate (capítulo 6) he encontrado bien poco a primera vista:

The <many-to-any> and <index-many-to-any> elements provide for true heterogeneous associations. These mapping elements work in the same way as the <any> element – and should also be used rarely, if ever.

Es decir, no dice nada de nada. Sobre ello reflexiona Oren Eini en su imprescindible blog, en lo que titula: Obscure N/Hibernate Feature. Pero claro, eso era por allá por 2005 y el framework aun estaba en mantillas. Como curiosidad, en el estupendo libro “Hibernate in Action” ni se menciona el asunto, aunque sigue siendo un título imprescindible.

El caso es que en el Capítulo 8 del manual de NHibernate si que dice algo más interesante sobre el tema que arroja algo de luz. Explica más o menos claro para qué sirve <any> y de ahí y a partir de la DTD del mapping se pueden sacar algunas conclusiones de cómo usar el <many-to-any>.

Éste permite mapear una colección a partir de un Id y un tipo de datos (que puede ser también un tipo personalizado que a partir del valor indicado devuelva el tipo correcto). De este modo, podemos crear colecciones de objetos heterogéneos que comparten una misma interfaz.

En mi caso tengo una tabla donde relaciono una serie de secciones (que contienen unos metadatos, pero no viene al caso), que se pueden asociar a cualquier entidad de negocio (que implemente IEntidad). No quería hacer una tabla para cada entidad que puede contener secciones (me quitaría flexibilidad), ni meter todas las entidades posibles en una misma tabla (son demasiado dispares en muchos aspectos), por lo que esta solución en mi caso era una tercera vía. Aquí mi ejemplo de mapeo:

<bag name="Entidades" table="cv_seccionesentidades">
    <key column="idseccion" />
    <many-to-any id-type="Int32" meta-type="class">
        <column name="tipo" />
        <column name="identidad" />
	</many-to-any>
</bag>

En la columna tipo, está el tipo de datos en formato de .NET (es decir, tipo + , + ensamblado) y en la de identidad se encuentra el id de alguna de las entidades mapeadas. Todo esto va a parar a un IList<IEntidad> genérico.

La verdad es que puede parecer una funcionalidad extraña y compleja pero aunque no es recomendable abusar de ella (digamos que va en contra de lo que es una base de datos relacional, ya que no hay relación en realidad), puede ser muy útil para algunos casos como el que se muestra en el ejemplo.

Si te ha gustado esta entrada, por favor deja un comentario o suscríbete al RSS para que puedas recibir todas las novedades en tu lector de feeds favorito.
This entry was posted in Programación and tagged , . Bookmark the permalink.

Leave a reply