6
NHibernate, ejemplo práctico Para abrir el blog no elegí mejor tema que el grandioso framework de persistencia, de cual puedo estar hablando sino es NHibernate. La idea principal de esta publicación será ni más ni menos que proporcionar un ejemplo integral de varias características que mucha falta hacen y que tanto cuesta aprender al comenzar con esta herramienta. Este artículo no tiene intención de ser detallista ni explicar puntualmente cada aspecto implementado, para ello podrá encontrar artículos mas destacados como por ejemplo el excelente articulo publicado en el Blog de Dario Quintana . La idea final es simplemente proporcionar un ejemplo que permita ver varias características funcionando juntas. Aspectos implementados Entre las características implementadas encontraran los siguientes puntos: Modelo completamente tipado Relaciones many-to-one, one-to-many y many-to-many Persistencia de enumerados Persistencia de campos nText (type="StringClob") Herencia table per class hierarchy <subclass>, table per subclass <joined-subclass> Herencia table per class hierarchy <subclass>, utilizando una formula en el <discriminator>. Consultas hql entre relaciones many-to-many Descargar Ejemplo Diagramas del Dominio Diagrama del dominio de la Institucion

NHibernate

  • Upload
    jeff

  • View
    1

  • Download
    0

Embed Size (px)

DESCRIPTION

Manual Nhibernate

Citation preview

NHibernate, ejemplo prctico

Para abrir el blog no eleg mejor tema que el grandioso framework de persistencia, de cual puedo estar hablando sino es NHibernate.

La idea principal de esta publicacin ser ni ms ni menos que proporcionar un ejemplo integral de varias caractersticas que mucha falta hacen y que tanto cuesta aprender al comenzar con esta herramienta.

Este artculo no tiene intencin de ser detallista ni explicar puntualmente cada aspecto implementado, para ello podr encontrar artculos mas destacados como por ejemplo el excelente articulopublicado en el Blog de Dario Quintana.

La idea final es simplemente proporcionar un ejemplo que permita ver varias caractersticas funcionando juntas.

Aspectos implementados

Entre las caractersticas implementadas encontraran los siguientes puntos:

Modelo completamente tipado

Relaciones many-to-one, one-to-many y many-to-many

Persistencia de enumerados

Persistencia de campos nText (type="StringClob")

Herencia table per class hierarchy , table per subclass

Herencia table per class hierarchy , utilizando una formula en el .

Consultas hql entre relaciones many-to-many

Descargar Ejemplo

Diagramas del Dominio

Diagrama del dominio de la Institucion

Diagrama del dominio de reserva de libros

Diagramas de persistencia en SQL Server 2005

Diagrama de Base de Datos de la Institucion

Diagrama de Base de Datos de las Reservas de libros

Persistencia de Enumerados

Un punto mas que importante para brinda consistencia al modelo, es la utilizacin de enumerados en al definicin del dominio de la aplicacin.

En la clase ClaseEntity, se observara un atributo de nombre FormaPago definido como un enumerado, por supuesto en la definicion de su mapper (Clase.hbm.xml) encontraran la definicin de de la propiedad

Se observa claramente la utilizacin de un mapper de enumerado (el cual esta alojado dentro del NHib.Infrastructure), el cual permitir recuperar el nmero asignado al tem del enumerado asignado.

Persistencia de campos nText

Un tema interesante para probar es la persistencia de atributos espaciales,comoes el caso de comentarios, los cuales deben contener texto que escapa a un simple descripcin. Es en estos casos que se utilizara en nText,existiendo enNHibernateuna forma especial de definir este tipo de mapeo.

En la clase LibroEntity, es justamente donde se hace uso de este, en el atributo Comentarios definido en el mapper como:

Es en la clase de test TestLibro.cs -> LargoComentarios(), donde se realiza una prueba de su correcta persistencia, comprobando que no se trunca el valor del atributo

Herencia

En la aplicacin encontraran tres tipos de herencia implementada, utilizando:

Tabla para todas las clasesEste primer tipo de implementacin lo ubicaran en la entidad LibroEntity, en esta se remarca la definicion de los atributos discriminator-value el cual toma un valor numerico cuyo tipo es definido en el tag Se aclara que el tipo de dato por defecto definido es del tipo de datos string, esto a simple vista pareciera no tener mayor implicancia, pero al momento de utilizar un con valores numricos, todas las clases debern tener definido un discriminator-value, aunque la clase principal no sea utilizada.

En el ejemplo la defincin del tag , al estar utilizando la interface ILibroEntity, debe definir un discriminator-value, con un valor que no es utilizado por el modelo como diferenciador en la herencia de clases, estodebe hace con el simple objetivo de evitar un error de tipos de datos.

Tabla para cada subclaseLa implementacin se podr observar en la clase ReservaEntity, a diferencia del ejemplo anteriorque utilizauna sola clase, no existe el discriminator-value, y es por medio de la relacion uno a uno de las tablas que semapean comose obtiene el tipo de objeto.

En este caso se hara uso de un tag de mapeo:, la cualdefinir cual es el atributo relacin entre las tablas, siendo esta la razn de utilizar Herencia utilizando formulas en el discriminatorEsta ser utilizada en los casos en donde se pretenda generalizar entidades que pueden ser agrupadas desde otro nivel de abstraccin que requiere el modelo analizado.

En el ejemplo sucedi con los convenios, (definido en la entidad ConvenioEntity) el cual describe la existencia de varios tipos de talleres y excursiones, que se pueden asociar a una institucin.

Pero el modelo solo necesitaba diferenciar entre convenios del tipo taller y excursin, para esto necesita agrupar distintos valores en un discriminator.

Adems para aumentar la complejidad el atributo esta definido con un carcter mientras que el mapeo har uso de un valor numrico.

Es por medio del atributo formula que se transformara el valor del discriminator de una valor del tipo carcter a uno numerico.

Se debe aclarar que este tipo de definiciones presentan un inconveniente, solo podrn recuperarse los distintos tipos de subclases definidas, pero no podrn persistirse, ya que es imposible por medio de la definicin de la formula saber que atributo de tipo especificar, esto deber realizarse implcitamente en la definicin de la clase a persistir.

Es por esta razn que se notara la definicin de un enumerado dentro de las subclases que permita diferenciar las distintas clases concretas de Convenios. La redefinicin del constructor permite forzar la especificacion al momento de crear una nueva subtipo de Convenio.

El framework necesita la especificacin de un constructor sin parmetros, pero para evitarsu utilizacines que se define como protected. Al igual que la definicin del atributo Tipo (tambin protected) que permitir ser utilizado solamentepor el mapper,permitiendo especificar el tipo concreto a persistir.

Ademasse debe entenderque por tratarse de un campo del tipo char, se realiza por medio del case la asignacin del valor correcto, si hubiera sido numrico se podra haber persistido el enumerado directamente como el caso visto en a persistencia de enumerados.

Consultas hql entre many-to-many

Si bien la definicin del mapeo de la navegacin entre entidades resulta de suma utilidad, hay ocasiones en donde se requiere obtener algn tipo de filtro aplicado al otro extremo de la relacin, es en este punto donde se har uso de las consultas HQL, y en ellas el operador JOIN.

Para visualizar un ejemplo de su implementacin se podrn visitar varios puntos donde fueron utilizados, destacando:

ProfesorRepository -> GetAlumnos(): Implementa un join en donde se recorren dos relaciones muchos a muchos. Esta podra ser testeada desde TestProfesores -> RecuperoAlumnos() AlumnoRepository -> GetByClase(): Define varias sobrecargas con diferente filtros que son aplicados a un join.

Eliminar en cascada Como es de suponer esta facilidad de actualizar la cascada de elemetos relacionados es de muchisima importancia, pero durante la utilizacin de la navegacin entre entidades me encontre con un pequeo detalle que quera remarcar. Se trata de la utilizacin de la propiedad inverse="true",esta es de suma importancia cuando se estautilizando navegacin bidireccional.

De no especificarse esta propiedad al momento de producirse,por ejemplo, la eliminacion de un objeto padre, sus hijos seran actualizados y al no encontrase la entidad superior generar una exception que indicara la imposibilidad de insertar null en el campo de la tabla.

Esto podria resolverse facilmente marcando el campo de relacin para que permita null en su contenido, pero no todos los tipos de realaciones en el modelo pueden hacer esto.

Un ejemplo del uso de esta propiedad podra encontrase enel achivo de mapeo de la entidadInstitucion (Institucion.hbm.xml), y la prueba de la eliminacion en cascada se encuantra en el test: TestInstituciones -> EliminoInstitucion()

Nota: Si quieren probar como funciona esta propiedad eliminenla del archivo de mapeo Institucion.hbm.xml, de la relacin con el Alumno por ejemplo, e intenten correr el test: TestInstituciones -> EliminoInstitucion(), para ver los resultados.

Tambien podran marcar el campos "Institucion"de la tabla "Alumnos", observarncomo sesoluciona el problema.

Implementacin En la aplicacin encontraranque esta formada por varias capas entre ellas la de Aplicacion y Presentacin, pero estas no estn implementadas, pues no era necesario para el objetivo de aprender NHibernate, simplemente con la utilizacin del proyecto de Test se pudo comprobar el correcto funcionamiento del framewok de persistencia. Se debe remarcar que el dominio debe ser tomado algo inventado, no perteneciante a un dominio existente, pensado simplemente para lograr el objetivo principal de verificar la funcionalidad de NHibernate.

Si bien el cdigo es sumamente til con tan solo visualizar el cdigo de los test, asi como tambin el de los mapper, es posible ejecutarlo si se conecta apropiadamentea una base de datos. Para ellos, como en la mayora de las aplicaciones, simplemente se debe modificar el app.config del proyecto de pruebas, apuntandolo a la DB que corresponda.

Para crear la estructura de la base de datos se encontrar un proyecto con los script de creacion de la estructura, o en caso contrario podran hacer usode los archivos .mdf y .ldf de la base de datos, adjuntandolos por medio de la opciones de attach del SQL Server 2005.

Para la ejecucin de los test hice uso de UnitRun, de esta forma poda ejecutarlos uno a uno en modo debug e ir analizando como se comporta cada uno.

Conclusin Espero antes que nada haber aportado un granito mas de arena a la investigacin de este potentsimo framework, apuntando principalmente aspectos un poco mas avanzados de los cuales es complicado encontrar ejemplo cerrados que los integre. Quedan varios puntos todava por probar, como ser el mapeo a store procedure, paginado, etc

Espero les sea de utilidad y cualquier duda, modificacin o error que encuentren sern bienvenidos.