August 13th, 2010

Fluent nHibernate

HAT

Fluent NHibernate logoDentro de Hexacta, el uso de nHibernate dentro de la población .Net se ha popularizado. El hecho de tener gente con experiencia en Hibernate ayudó también a la inclución de nHibernate en nuestro stack tecnológico.

UPDATE: la siguiente parte de este post está disponible aquí

Por la misma razón, algunas prácticas importadas de nuestros primos de Java continuan en forma casi indiscutida, una de ellas, la configuración de mapeos mediante XML y eventualmente la misma configuración de la factory por XML. Si bien XML es una opción válida, vale la pena mirar opciones.

Una alternativa es la de usar atributos para el mapeo, está disponible desde las primeras versiones de nHibernate pero no cuenta con el apoyo popular de aquellos más puristas que no desean ver el su modelo de dominio con datos foráneos como es la persistencia.


Otra opción, la que ocupa este post, es la de Fluent nHibernate. Esta aproximación a la configuración de mapeos, tiene sus pilares sobre ciertas ideas:

  • El mapeo XML y el refactor de código no tienen razón de estar tan fuertemente ligados.
  • Siempre dentro de lo posible, se debe aprovechar las ventajas de una IDE moderna, lo que exige el minimizar las cadenas mágicas.
  • XML es verborrágico por naturaleza y por inducir a la repetición.

El objetivo de este post es el de ver casos muy sencillos de mapeo y ver los beneficios que puede aportar el uso de Fluent nHibernate frente al XML tradicional, para ello voy a utilizar un pequeño modelo muy simplificado de un blog. Este modelo no está diseñado para ver las características más avanzadas de nHibernate, sino para hacer una pequeña comparación en un caso muy simple. En futuras iteraciones espero poder mirar las características más avanzadas y ver si Fluent nHibernate muestra sus limitaciones que solo puedan superarse en forma razonable con otra técnica de mapeo.

Modelo

Un Blog tiene Posts, estos Posts están escritos por Autores que pertenecen al Blog y se encuentran en un estado (EstadoPostEnum) que puede ser publicado o como draft. Los Posts pueden tener Categorías y Etiquetas que son globales al Blog. Estos Posts pueden también tener Comentarios y estos Comentarios pueden tener respuestas (en su otra forma de Comentario).

Para probar el mapeo de una entidad sencilla, se puede usar la entidad Autor. En C# está definida de la siguiente forma:

Esta entidad, sería mapeada con XML de la siguiente manera:

Debe quedar claro que este es el absolutamente mínimo mapeo necesario para esta clase. nHibernate va a ser responsable de mapear los tipos Net y SQL en base al uso de reflection y del provider de la base de datos, estamos asumiendo claramente que no existe una base de datos previa o que si existe se ajusta exactamente o nuestro modelo.

Para comparar, podemos ver la versión Fluent. En este caso, no hay XML, sino que se generan clases de mapeo. Para nuestra entidad Autor, la clase de mapeo se vería como:

Fluent nHibernate (usando ClassMap<>) va a colaborar con nHibernate para generar nuestro mapeo. Una ventaja clara de esta aproximación es no tener más cadenas mágicas en nuestro código, si decido cambiar el atributo Descripcion por AutorEmail, solo debo renombrarlo y el mapeo será actualizado. El caso con XML no es tan sencillo, voy a tener que actualizarlo haciendo referencia a la nueva propiedad.

Si en cambio decido modificar el esquema de la base de datos y llamar al campo Email como AutorEmail, no voy a tener otra salida más que modificar el mapeo.

Con XML:

Con Fluent:

Lamentablemente ya apareció una cadena mágica (“AutorEmail”) pero al menos está haciendo referencia a un campo de una tabla y no un nombre que pertenece exclusivamente a nuestro modelo de objetos.

Un mapeo levemente más complicado es el de Post. Sus dos versiones:

Con XML:

Con Fluent:

En este caso, es más que claro que Fluent nHibernate tiene un resultado más limpio. Con respecto a los key que no se definen en el mapeo Fluent pero si son generados (Blog_id en Post, Post_id en Comentario, etc), este framework hace un uso extensivo de convenciones (modificables) de nombres y mapeos. Visualmente el resultado de generar el esquema desde nHibernate:

Con XML:

Resultado del mapeo con XML

Con Fluent:

Resultado del mapeo con Fluent nHibernate

Personalmente encuentro más fácil de leer lo generado por Fluent, especialmente el nombre de las tablas de las relaciones many-to-many. Aunque por otro lado:

  • El mapeo automático de Fluent no produjo las primary keys de las tablas intermedias, las tuve que agregar.
  • La propiedad Estado de Post se mapeo a un tipo nvarchar, siendo un enum. El mapeo XML generó un int en este caso, lo cual al menos para mi, es preferible. Esto es solucionable mediante el uso de convenciones.

De cualquier forma, espero que este pequeño ejemplo haya servido para mostrar las ventajas de Fluent. Adjunto código fuente que crea el ddl para este modelo en un archivo de texto (el dialecto es Sql Server 2008).

Share Button

6 comentarios a “Fluent nHibernate”

  1. Diego Kogan says:

    Muy groso!
    Estaría bueno que alguien haga lo mismo para el mundo java (tal vez usando groovy…)

    Saludos!

  2. Leo says:

    Muy bueno lo de eliminar las cadenas mágicas! Cuando cambias cosas en la base no te queda otra, pero por lo menos te queda atado a modificaciones manuales solo de un lado. El modelo no se mancha.

  3. Kurt Wood says:

    My spanish is a bit rusty but the examples are clear enough. Keep it up guys. I love your country.

  4. [...] This post was Twitted by cristianelopez [...]

  5. Paulo Soto says:

    Otro framework similar al que creo vale la pena pegarle una mirada es ConfORM http://code.google.com/p/codeconform/

  6. Banzai says:

    Muy post, bastante explicito. pero me gustaria hacer una pregunta, como puedo crear una tabla que contenga una llave primaria compuesta y que no sean producto de la relacion con otras dos tablas, sencillamente quiero crear una tabla que tenga como id la comninacion de dos

Dejar un comentario