NHibernate :Modelo de Persistencia de Datos en .NET

Hola , por estos dias , ando aprendiendo NHibernate un framework o Motor de persistencia de datos basados en Hibernate , este utimo implementado por un buen tiempo para Java.

Ahora se preguntaran que es Motor de Persistencia de datos , segun wikipedia

“Estos motores facilitan el mapeo objeto-relacional de atributos entre una base de datos relacional tradicional y suplen la funcionalidad de una Base de datos orientada a objetos. Estos motores buscan solucionar el problema de la diferencia entre los dos modelos usados hoy en día para organizar y manipular datos: El usado en la memoria de la computadora (orientación a objetos) y el usado en las bases de datos (modelo relacional). Para lograr esto permite al desarrollador detallar cómo es su modelo de datos, qué relaciones existen y qué forma tienen.”

NHibernate nos permite:

NHibernate es la conversión de Hibernate de lenguaje Java a C# para su integración en la plataforma .NET. Al igual que muchas otras herramientas libres para esta plataforma, NHibernate también funciona en Mono.

Al usar NHibernate para el acceso a datos el desarrollador se asegura de que su aplicación es agnóstica en cuanto al motor de base de datos a utilizar en producción, pues NHibernate soporta los más habituales en el mercado: MySQL, PostgreSQL, Oracle, MS SQL Server, etc. Sólo se necesita cambiar una línea en el fichero de configuración para que podamos utilizar una base de datos distinta.”

una primera demo en Consola: (este ejemplo lo tome de Dario Quintana

Yo despues lo implemente en Windows , lo separe en capas , tambien lo implemente a Oracle y me hize unos reportes , ire liberando poco a poco las demos , y al final , toda la solucion completa.

NHibernate: 1.2

Motor: SQL Server 2005

Plataforma: Windows XP SP3

1.- Crear Nuestras tablitas: , Primero Crear una base de datos , yo en mi caso le puse “NH01″ Aqui el script:

CREATE TABLE [dbo].[Factura](
    [IdFactura] [int] IDENTITY(1,1) NOT NULL,
    [Fecha] [datetime] NOT NULL,
PRIMARY KEY CLUSTERED
(
    [IdFactura] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Producto](
    [IdProducto] [int] IDENTITY(1,1) NOT NULL,
    [Categoria] [nvarchar](255) NULL,
    [Nombre] [nvarchar](255) NULL,
PRIMARY KEY CLUSTERED
(
    [IdProducto] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[LineaFactura](
    [IdLineaFactura] [int] IDENTITY(1,1) NOT NULL,
    [Cantidad] [int] NULL,
    [Precio] [decimal](19, 5) NULL,
    [IdFactura] [int] NULL,
    [IdProducto] [int] NULL,
PRIMARY KEY CLUSTERED
(
    [IdLineaFactura] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N’[dbo].[FK840F0A963DE64B1F]‘) AND parent_object_id = OBJECT_ID(N’[dbo].[LineaFactura]‘))
ALTER TABLE [dbo].[LineaFactura]  WITH CHECK ADD  CONSTRAINT [FK840F0A963DE64B1F] FOREIGN KEY([IdFactura])
REFERENCES [dbo].[Factura] ([IdFactura])
GO
ALTER TABLE [dbo].[LineaFactura] CHECK CONSTRAINT [FK840F0A963DE64B1F]
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N’[dbo].[FK840F0A96C45CE1E4]‘) AND parent_object_id = OBJECT_ID(N’[dbo].[LineaFactura]‘))
ALTER TABLE [dbo].[LineaFactura]  WITH CHECK ADD  CONSTRAINT [FK840F0A96C45CE1E4] FOREIGN KEY([IdProducto])
REFERENCES [dbo].[Producto] ([IdProducto])
GO
ALTER TABLE [dbo].[LineaFactura] CHECK CONSTRAINT [FK840F0A96C45CE1E4]
 

2.- Crear una Aplicacion Windows

image

Crear una Apliacion Windows con esa estructura:

Clases : FACTURA.cs , LINEAFACTURA.cs,PRODUCTO.cs ; son clases comunes , a continuacion detallo , su implementacion.

FACTURA.cs

namespace WinApp.Entidades
{
    [Serializable]
    public class FACTURA : IEquatable<FACTURA>
    {
        private int id;
        private DateTime fecha;
        public virtual int IDFACTURA
        {
            get { return id; }
            set { id = value; }
        }        public virtual DateTime FECHA
        {
            get { return fecha; }
            set { fecha = value; }
        }

#region IEquatable<Factura> Members

public bool Equals(FACTURA other)
        {
            if (this == other) return true;
            if (other.id == this.id) return true;
            return false;
        }
        #endregion
    }

LINEAFACTURA.cs

namespace WinApp.Entidades
{
    [Serializable]
    public class LINEAFACTURA : IEquatable<LINEAFACTURA>
    {
        private int id;
        private int factura;
        private int producto;
        private decimal precio;
        private int cantidad;        public virtual int IDLINEAFACTURA
        {
            get { return id; }
            set { id = value; }
        }

public virtual int IDFACTURA
        {
            get { return factura; }
            set { factura = value; }
        }

public virtual int IDPRODUCTO
        {
            get { return producto; }
            set { producto = value; }
        }

public virtual decimal PRECIO
        {
            get { return precio; }
            set { precio = value; }
        }

public virtual int CANTIDAD
        {
            get { return cantidad; }
            set { cantidad = value; }
        }

#region IEquatable<LineaFactura> Members

public bool Equals(LINEAFACTURA other)
        {
            if (other == this) return true;
            if (other.IDLINEAFACTURA == this.IDLINEAFACTURA) return true;
            return false;
        }

#endregion
    }
}

PRODUCTO.cs

namespace Entidades
{
    [Serializable]
    public class PRODUCTO : IEquatable<PRODUCTO>
    {
        private int id;
        private string nombre;
        private string categoria;
        private IList<LINEAFACTURA> lineas;        public PRODUCTO(string nombre, string categoria): this()
        {
            this.NOMBRE = nombre;
            this.CATEGORIA = categoria;
        }

public PRODUCTO()
        {
            lineas = new List<LINEAFACTURA>();
        }

public virtual int IDPRODUCTO
        {
            get { return id; }
            set { id = value; }
        }

public virtual string NOMBRE
        {
            get { return nombre; }
            set { nombre = value; }
        }

public virtual string CATEGORIA
        {
            get { return categoria; }
            set { categoria = value; }
        }

public virtual IList<LINEAFACTURA> Lineas
        {
            get { return lineas; }
            set { lineas = value; }
        }

#region IEquatable<PRODUCTO> Members

public bool Equals(PRODUCTO other)
        {
            if (this == other) return true;
            if (this.id == other.id) return true;
            return false;
        }

#endregion
    }

Mapeos:

Factura.hbm.xml

<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-mapping xmlns=”urn:nhibernate-mapping-2.2″ assembly=”WinApp” namespace=”WinApp.Entidades”>
  <class name=”FACTURA” table=”FACTURA”>
    <id name=”IDFACTURA” column =”IDFACTURA” type=”int” unsaved-value=”0″>
      <generator class=”identity”/>
    </id>
    <property name=”FECHA” type =”DateTime” not-null=”true”/>
  </class>
</hibernate-mapping>

LineaFactura.hbm.xml

<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-mapping xmlns=”urn:nhibernate-mapping-2.2″ assembly=”WinApp” namespace=”WinApp.Entidades”>  <class name=”LINEAFACTURA”>
    <id name=”IDLINEAFACTURA” column =”IDLINEAFACTURA” type=”int” unsaved-value=”0″>
      <generator class=”identity”/>
    </id>
    <property name=”CANTIDAD” type=”int” />
    <property name=”PRECIO” type =”Decimal”/>

<property name=”IDFACTURA” type=”int”/>
    <property name=”IDPRODUCTO” type=”int”/>
  </class>
</hibernate-mapping>

Producto.hbm.xml

<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-mapping xmlns=”urn:nhibernate-mapping-2.2″ assembly=”WinApp” namespace=”WinApp.Entidades”>
  <class name=”PRODUCTO”>
    <id name=”IDPRODUCTO” column =”IDPRODUCTO” type=”int” unsaved-value=”0″>
      <generator class=”identity”/>
    </id>
    <property name=”CATEGORIA” type =”string”/>
    <property name=”NOMBRE” type=”string”/>
    <bag name=”Lineas”>
      <key column=”IDPRODUCTO”/>
      <one-to-many class=”LINEAFACTURA”/>
    </bag>
  </class>
</hibernate-mapping>

Este es Nuestro Diseño de Formulario:

image

En el Boton Agregar:

       if (this.txtProducto.Text.Trim().Length != 0)
            {
                int cant = Int32.Parse(this.txtCantidad.Text);
                decimal precio = decimal.Parse(this.txtPrecio.Text);
                decimal total = cant * precio;
                ListViewItem listItem = new ListViewItem(this.txtProducto.Text);
                listItem.SubItems.Add(this.txtCategoria.Text);
                listItem.SubItems.Add(this.txtPrecio.Text);
                listItem.SubItems.Add(this.txtCantidad.Text);
                listItem.SubItems.Add(total.ToString());
                listView1.Items.Add(listItem);
                Limpiar();
            }
            else
            {
                MessageBox.Show(this, “Ingrese Producto”, “Alerta”);
            }//Agrego Los Productos que Ingreso dentro del ListView

En el Boton Guardar:

            Configuration cfg = new Configuration();
            cfg.Configure(“hibernate.cfg.xml”);
            ISessionFactory sesiones = cfg.BuildSessionFactory();
            ISession sesion = sesiones.OpenSession();
            FACTURA factura = new FACTURA(fecha.Value);
            foreach (ListViewItem listItem in this.listView1.Items)
            {
                string ProductoNombre = listItem.SubItems[0].Text;
                string Categoria = listItem.SubItems[1].Text;
                string Precio = listItem.SubItems[2].Text;
                string Cantidad = listItem.SubItems[3].Text;
                PRODUCTO objProducto = new PRODUCTO(ProductoNombre, Categoria);
                sesion.Save(objProducto);
                LINEAFACTURA objLinea = new LINEAFACTURA(factura, objProducto, Decimal.Parse(Precio), Int32.Parse(Cantidad));
                sesion.Save(objLinea);
                factura.Lineas.Add(objLinea);
                //sesion.Delete(objProducto);
                //sesion.Delete(objLinea);                                  
            }
            sesion.Save(factura);          
            sesion.Flush();
            sesion.Close();

Finalmente nuestro Archivo de Configuracion: hibernate.cfg.xml

<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-configuration  xmlns=”urn:nhibernate-configuration-2.2″>
  <session-factory>
    <property name=”connection.provider”>NHibernate.Connection.DriverConnectionProvider</property>
       <!– Oracle 9i and 10g use the same dialect –>
       <property name=”dialect”>NHibernate.Dialect.MsSql2005Dialect</property>     
       <property name=”connection.driver_class”>NHibernate.Driver.OracleClientDriver</property>
       <property name=”connection.connection_string”>Data Source=(TU PC);Initial Catalog=NH01;Integrated Security=True</property>     
       <property name=”show_sql”>true</property>
       <mapping assembly=”WinApp”/>     
  </session-factory>
</hibernate-configuration>

Espacios de Nombres a Importar:

using WinApp.Entidades;//Propio donde tenemos nuestras clases serializables
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;

Esta fue una demo NHibernate usando SQL Server 2005

Espero les haya servido , en el segundo Post , hare una demo para Oracle 9i, Muchas Gracias.

Jose Fabricio Rojas

DESCARGATE LA DEMO


About this entry