Angel "Java" Lopez

NET, Java, PHP y Desarrollo de Software

This Blog

Syndication

Search

Tags

Community

Email Notifications

Archives

.NET

ASP.NET

Windows Form

VB.NET

C#

Sitios

Blogs

NHibernate 3 (Parte 3) Tabla por Clase Concreta

Anterior Post
Siguiente Post

Quiero usar el mismo dominio que en mi anterior post:

 

but this time, I want two tables: one for Notes, another for Pages:

La solución tiene dos proyectos: una librería de clases conteniendo el dominio, y un proyecto de consola:

El código está en mi AjCodeKatas Google code project, en el directorio trunk/NHibernate/ItemsTablePerConcreteClass. El código no incluye las librerías de NHibernate, hay que agregarlas a las referencias de la solución. Como en el ejemplo previo, agregué como referencias al proyecto de consola: NHibernate.dll del directorio de NHibernate llamado Required_Bins y NHibernate.ByteCode.Castle del directorio Required_For_LazyLoading\Castle. Agregué también los archivos .xsd  (los esquemas XML para soportar el manejo de intellisense cuando se escriben los archivos de mapeo) desde el directorio de NHibernate llamado Required_Bins.

Pueden bajar el código fuente directamente desde NHibernate3ItemsTablePerConcreteClass.zip, si no quieren bajarlo con un cliente de SVN desde el proyecto de Google Code. Si necesitan las librerías de NHibernate 3.x, puede visitar http://nhforge.org o bajar las que utilicé en mi primer ejemplo NHibernate3SimpleMapping.zip, ahí están incluidas. Pueden ver mi primer post para otros detalles (por ejemplo, no olviden poner los archivos de mapeao como recursos embebidos, si van a construir su propia solución).

Noten que las clases del dominio siguen siendo las mismas: no cambiaron desde el anterior ejemplo. Lo que cambia es la forma de mapeo, los archivos de mapeo, no el código. Esta es una prueba de la independencia del dominio de nuestra estrategia de mapeo.

Este es el Item.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerConcreteClass.Domain"
namespace="ItemsTablePerConcreteClass.Domain">
  <class name="Item" abstract="true">
    <id name="Id">
      <generator class="guid.comb" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Description" not-null="true" />
  </class>
</hibernate-mapping>

 

 

Primero removí la columna discriminator. No hay tal columna, porque no hay ahora un tabla de Items. Agregué el atributp table. I added the attribute abstract=”true”. Si olvidan agregarlo, NHibernate “piensa” que tienen una tabla concreta para guardar los objetos de esta clase. Pueden removerla, si tiene Items que no son Notas ni Páginas. No es el caso de este ejemplo que quiero implementar: los únicos items “reales” son Notas o Páginas. Item es una abstracción del dominio.

El Note.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerConcreteClass.Domain"
namespace="ItemsTablePerConcreteClass.Domain">
  <union-subclass name="Note" extends="Item" table="Notes">
    <property name="Content" />
  </union-subclass>
</hibernate-mapping>

 

 

Agregué el atributo table=”Notes”. Y el nuevo elemento que se usa es union-subclass, en vez de subclass como en el anterior ejemplo. Este nuevo elemento “dice”: “la tabla de esta clase CONTIENE las columnas a grabar con los valores de la clase padre”. Esto es: las columnas de la tabla son la unión de las propiedades de la clase padre y de esta clase.

Cambios similares en Page.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerConcreteClass.Domain"
namespace="ItemsTablePerConcreteClass.Domain">
  <union-subclass name="Page" extends="Item" table="Pages">
    <property name="Url"/>
  </union-subclass>
</hibernate-mapping>

 

 

El código principal es prácticamente el mismo que en el anterior ejemplo:

ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession())
{
    using (ITransaction tx = session.BeginTransaction())
    {
        Page page1 = new Page();
        page1.Title = "Technical Blob";
        page1.Description = "My Personal Technical Blob in English";
        page1.Url = "http://ajlopez.wordpress.com";
        Page page2 = new Page();
        page2.Title = "My Personal Blob";
        page2.Description = "My Personal Blob in Spanish";
        page2.Url = "http://ajlopez.zoomblog.com";
        Note note1 = new Note();
        note1.Title = "To Do";
        note1.Description = "My To Do List";
        note1.Content = "Practice NHibernate";
        session.Save(page1);
        session.Save(page2);
        session.Save(note1);
        var items = session.Query<Item>(); ;
        foreach (Item item in items)
            System.Console.WriteLine(string.Format("Item {0}", item.Title));
        tx.Commit();
        session.Close();
    }
}

 

 

excepto que esta vez, comencé a usar Session.Query<T>, un nuevo método de extensión para las sesiones de NHibernate, que retorna un IQueryable<T> que soporta Linq contra NHibernate y la base de datos de persistencia. Para usar ese método HAY QUE AGREGAR:

using NHibernate.Linq;

sino, no aparecerá como disponible. Recuerden: es un método de extensión, no es un método “natural” de ISession.

Mis fuentes de información:

El libro: Jason Dentler’s NHibernate 3.0 Cookbook

http://www.nhforge.org/doc/nh/en/index.html#mapping-declaration-unionsubclass

http://www.nhforge.org/doc/nh/en/index.html#inheritance

Próximos pasos: implementar Tabla por Clase, explorar relaciones uno-a-varios, colecciones “lazy”, etc…

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Published Tue, Apr 19 2011 0:30 by lopez

Filed under: , ,

Comments

# NHibernate 3 (Parte 4) Tabla Por Clase@ Tuesday, April 19, 2011 8:26 PM

Previous post Next post En los anteriores posts ( Tabla por Jerarquía , Tabla por Clase Concreta ), implementé

Angel "Java" Lopez

# re: NHibernate 3 (Parte 3) Tabla por Clase Concreta@ Monday, June 13, 2011 4:52 PM

Como elimino y actualizo datos

carlos

Leave a Comment

(required) 
(required) 
(optional)
(required) 
If you can't read this number refresh your screen
Enter the numbers above: