Videos sobre .NET

Presentaciones sobre .NET:

Mapeo de secuencias de PostgreSQL en NHibernate

En PostgreSQL, para que una tabla tenga un campo autoincrementable se puede usar SERIAL o BIGSERIAL, éstos últimos en realidad no son tipos de datos reales puesto que internamente se crean secuencias para los campos que usan esta sintáxis, por ejemplo:

sql:
CREATE TABLE blog_category (
    id serial NOT NULL,
    name character varying,
    description character varying
);
code:
test=> \d blog_category
                                 Tabla «public.blog_category»
   Columna   |       Tipo        |                       Modificadores
-------------+-------------------+------------------------------------------------------------
 id          | integer           | not null default nextval('blog_category_id_seq'::regclass)
 name        | character varying |
 description | character varying |
 

Para representar representar esa tabla en NHibernate, hay que hacer algo adicional a lo que normalmente se hace con otro tipo de bases de datos:

xml:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Buayacorp.Domain.BlogCategory, Buayacorp.Domain" table="Blog_Category">
    <id name="Id" type="Int32" unsaved-value="0">
      <column name="Id" length="4" sql-type="int" unique="true"/>
      <generator class="native">
        <param name="sequence">blog_category_id_seq</param>
      </generator>
    </id>
    <property name="Name" type="String">
      <column name="Name" length="255" sql-type="varchar"/>
    </property>
    <property name="Description" type="String">
      <column name="Description" length="3000" sql-type="varchar"/>
    </property>
    <bag name="Blogs" inverse="true" lazy="true" cascade="all-delete-orphan">
      <key column="category_id"/>
      <one-to-many class="Buayacorp.Domain.Blog, Buayacorp.Domain"/>
    </bag>
  </class>
</hibernate-mapping>

En las líneas resaltadas se puede apreciar que para mapear el campo id es necesario especificar el nombre de la secuencia definida en la base de datos, esto es porque para generar los nuevos valores para ese campo se usa la función nextval, que justamente toma como parámetro ese nombre. Por ejemplo, para la siguiente porción de código:

csharp:
using System;
using System.Collections.Generic;
using System.Text;
using NHibernate.Cfg;
using NHibernate;
using Buayacorp.Domain;
using System.Xml;

namespace Buayacorp.Demo
{
    static class Program
    {
        static void Main()
        {
            Configuration cfg = new Configuration();
            cfg.AddAssembly("Buayacorp.Domain");
            ISessionFactory factory = cfg.BuildSessionFactory();

            ISession session = null;
            ITransaction transaction = null;
            try
            {
                session = factory.OpenSession();
                transaction = session.BeginTransaction();

                BlogCategory cat = new BlogCategory("Tecnología", "Blogs con información sobre lo último en tecnología...");
                session.Save(cat);

                Console.WriteLine(cat.Id); // cat.Id ya tiene un valor generado
               
                transaction.Rollback();
            }
            finally
            {
                if (session != null)
                    session.Close();
            }
        }
    }
}

Las consultas que se ejecutan en el servidor de base de datos son:

code:
2007-04-22 17:44:38 PET LOG:  sentencia: SELECT oid, typname FROM pg_type WHERE typname IN ('unknown', 'refcursor', 'char', 'bpchar', 'varchar', 'text', 'name', 'bytea', 'bit', 'bool', 'int2', 'int4', 'int8', 'oid', 'float4', 'float8', 'numeric', 'inet', 'money', 'date', 'time', 'timetz', 'timestamp', 'timestamptz', 'point', 'lseg', 'path', 'box', 'circle', 'polygon')
2007-04-22 17:44:38 PET LOG:  sentencia: BEGIN; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
2007-04-22 17:44:38 PET LOG:  sentencia: select nextval ('blog_category_id_seq')
2007-04-22 17:44:38 PET LOG:  sentencia: ROLLBACK
2007-04-22 17:44:38 PET LOG:  sentencia: unlisten *

Para los curiosos, pueden descargar el archivo que contiene el código mostrado en esta entrada.

NHibernate y PostgreSQL

Esta es la primera de dos entradas donde mostraré -de manera básica, como realizar reportes usando NHibernate , PostgreSQL y los controles para Reportes (ReportViewer) que trae cualquier instalación de Visual Studio 2005 -corríjanme si me equivoco 🙂 .

NHibernate es un framework que hace el mapeo de un modelo orientado a objetos a uno relacional.

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.

NHibernate tiene demasiadas características como para hablar sobre alguna en especial en este par de entradas, además que ya se ha escrito bastante sobre estos temas. En este apartado, sólo quiero hacer notar un pequeño detalle al momento de trabajar con PostgreSQL como base de datos.

xml:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="nhibernate" type="System.Configuration.NameValueSectionHandler" />
  </configSections>
  <nhibernate>
    <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
    <add key="hibernate.dialect" value="NHibernate.Dialect.PostgreSQLDialect" />
    <add key="hibernate.connection.driver_class" value="NHibernate.Driver.NpgsqlDriver" />
    <add key="hibernate.connection.connection_string"
         value="Server=192.168.1.20;Database=test;User Id=alex;Encoding=LATIN1;" />

  </nhibernate>
</configuration>

Como se puede apreciar en el código mostrado, la cadena de conexión incluye un parámetro Encoding -sólo sirve para PostgreSQL, donde se especifica la codificación de caracteres que usará nuestra aplicación en la comunicación con el servidor de Base de Datos, si bien es cierto que PostgreSQL intentará hacer automáticamente una conversión entre la codificación definida en el servidor y la del cliente, es recomendable utilizar explícitamente la misma codificación en ambos extremos.

En la siguiente entrada, se tocará específicamente el diseño de reportes usando un ensamblado que contiene nuestro modelo.

Class Diagram for NHibernate Sample