cracks for soft
cracksmachine
cracks serials db
crackssearchdb
download rapidshare files
downloadcracksdb
free cracks 4 all
download free serials
dola dll warez
keygen machine
Mono + NHibernate + SQLite « il libero

Het downloaden van klingeltöne, Download von klingeltöne, Het downloaden van klingeltöne, Descargar tonos, Téléchargez des sonneries, scarica suonerie, Beltonen downloaden, Nedlasting av ringetoner, Download ringtones

Mono + NHibernate + SQLite

Después de usar por tanto tiempo Gentle.NET, un ORM que ha sido discontinuado, he decidido al fin comenzar a estudiar NHibernate. Los ejemplos que dan en los manuales y páginas son para Windows (con MS .NET) y SQL Server. Trabajando en GNU/Linux, hice las pruebas con SQLite.

El problema es que el driver utilizado por NHibernate para esta base de datos utiliza un binding desactualizado. Además Mono trae una implementación mejor, que soporta el standard ADO.NET 2.0, que es Mono.Data.Sqlite, disponible a partir de la versión 1.2.4.

El post es especialmente útil para aquellos que quieran utilizar en GNU/Linux (yo uso Ubuntu Gutsy), con Mono, NHibernate y SQLite, utilizando el binding Mono.Data.Sqlite. Si bien puede parecer esto tan fácil como seguir el documento QuickStart y cambiar las opciones correspondientes, no lo es si se intenta utilizar SQLite. Por eso, en este post no voy a explicar todas las cosas, ya que no me interesa y se pueden aprender en la documentación, sino que voy a desarrollar un ejemplo muy sencillo y mostrar cómo utilizar SQLite, ya que hay que solucionar unos problemas no muy triviales.


Cabe aclarar que, si bien todavía no lo he probado, los archivos de mapeo (hbm.xml) y el schema SQL se pueden autogenerar.

Primero creo la tabla que almacenerá los objetos en un archivo llamado, por ejemplo, data.db.sql:

DROP TABLE IF EXISTS personas;

CREATE TABLE personas (
	id integer primary key,
	nombre varchar(20),
	apellido varchar(20)
);

Para el ejemplo utilicé la última versión de SQLite. Para crear la base de datos en el archivo data.db, ejecutamos:

$ sqlite3 data.db < data.db.sql
$

La clase de ejemplo (Persona.cs):

using System;

namespace PruebaNHibernate
{
	public class Persona
	{
		private int id;
		private string nombre;
		private string apellido;

		public Persona()
		{
		}

		public int Id {
			get { return id; }
			set { this.id = value; }
		}

		public string Nombre {
			get { return nombre; }
			set { this.nombre = value; }
		}

		public string Apellido {
			get { return apellido; }
			set { this.apellido = value; }
		}
	}
}

Luego hay que escribir el archivo de mapeo, que es un XML.




	
		
			
		


	

Este archivo se debe agregar como recurso en MonoDevelop.

Luego escribimos el archivo de configuración para nuestra aplicación (app.config):



	

Nota: Debido a problemas con el hosting no puedo colocar, arriba, el string correcto en la última parte. La palabra prohibida "p r o x y" (sin espacios) tiene un espacio de más entre la "x" y la "y". En fin, deshabilito en esas lineas la comprobación de clases p r o x y.

Luego en un archivo como Main.cs agrego código en el método principal Main para jugar con todo esto:

using System;
using NHibernate;
using NHibernate.Cfg;

namespace PruebaNHibernate
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			Configuration conf = new Configuration();
			/* Con la siguiente línea leo todo los archivos con extensión
			 * hbm.xml embebidos como recurso en el assembly especificado */
			conf.AddAssembly("PruebaNHibernate");

			ISessionFactory sessionFactory = conf.BuildSessionFactory();

			ISession s = sessionFactory.OpenSession();

			ITransaction tx = s.BeginTransaction();

			Persona p = new Persona();
			p.Nombre = "Milton";
			p.Apellido = "Pividori";
			s.Save(p);
			tx.Commit();

			Console.WriteLine("p - Id: " + p.Id);
			Console.WriteLine("p - Nombre: " + p.Nombre);
			Console.WriteLine("p - Apellido: " + p.Apellido);
			Console.WriteLine();

			Persona p2 = (Persona)s.Load(typeof(Persona), p.Id);

			Console.WriteLine("p2 - Id: " + p2.Id);
			Console.WriteLine("p2 - Nombre: " + p2.Nombre);
			Console.WriteLine("p2 - Apellido: " + p2.Apellido);
			Console.WriteLine();

			/* Verifico si son el mismo objeto p y p2, ya que estamos
			 * dentro de la misma sesión */
			if (p == p2)
				Console.WriteLine("p y p2 son el mismo objeto");

			p2.Apellido = "Paduán";

			s.Flush();

			s.Close();
		}
	}
}

En el proyecto agregué estas referencias:

  • NHibernate.dll
  • System

Ahora vamos a lo que nos interesa. En el archivo app.config (que al compilar se traducirá a .exe.config en el directorio de salida), observemos estas lineas:

        ...
        
        ...

NHibernate trae un driver para SQLite, como dije al principio, pero que utiliza un provider que fue discontinuado. Por lo tanto, para utilizar Mono.Data.Sqlite, cree una clase en mi assembly (PruebaNHibernate) con el nombre que se indica allí (MonoDataSqliteDriver):

using System;
using NHibernate.Driver;

namespace PruebaNHibernate
{
	public class MonoDataSqliteDriver : ReflectionBasedDriver
	{
		public MonoDataSqliteDriver()
			: base("Mono.Data.Sqlite",
			       "Mono.Data.Sqlite.SqliteConnection",
			       "Mono.Data.Sqlite.SqliteCommand")
		{
		}

		public override bool UseNamedPrefixInSql
		{
			get { return true; }
		}

		public override bool UseNamedPrefixInParameter
		{
			get { return true; }
		}

		public override string NamedPrefix
		{
			get { return "@"; }
		}

		public override bool SupportsMultipleOpenReaders
		{
			get { return false; }
		}
	}
}

En el constructor de la misma le paso a mi clase padre los argumentos que necesita: nombre del assembly (en este caso "Mono.Data.Sqlite"), clase para crear la conexión y ejecutar comandos. Desconozco los detalles de SQLite, así que copié los métodos sobreescritos del driver viejo.

No pude hacer que NHibernate cargue el assembly "Mono.Data.Sqlite" desde el GAC, así que hay que copiarlo al directorio del ejecutable. Es necesario copiar otros archivos, como las dependencias de NHibernate y la base de datos (data.db). Se pueden bajar el proyecto completo para MonoDevelop aquí. El archivo obviamente no es un png, pero sino no lo puedo subir :)

Ahora bien, hay un problemita... el archivo System.Data.dll que viene con Mono 1.2.4 en Gutsy tiene un bug que hará que el ejemplo no funcione. El mismo ya fue solucionado en la versión 1.2.6. Así que, como workaround, pueden bajarse el paquete de Debian libmono-system-data2.0-cil correspondiente a la versión 1.2.6 de Mono y sobreeescribir ese archivo, que se ubica en /usr/lib/mono/gac/System.Data/2.0.0.0__b77a5c561934e089/. Reporté el problema en Ubuntu, así que quizá lo actualicen dentro de poco.

Con esto podremos utilizar SQLite con NHibernate, bajo Mono, con un binding actualizado.

Google
 

  • Hola Milton comoandas. che men. soy gerardo de sqlite Latino me gustaria conctarme con vos saludos gerardo
    sqlite-latino.blogspot.com
  • Yo no necesito poner todo el path completo al archivo de base de datos, ni en GNU/Linux ni en Windows (ni con Mono ni con MS .NET).

    No se si Mono funcionará con esas bases de datos, pero yo creo que sí, no debería fallar.

    Bueno, me alegro mucho que hayas logrado esto. Saludos!
  • David Benito
    Ya lo he conseguidooo!! weee! wee!

    Se ve que tenia que poner en la cadena de conexión todo el path completo del Data Source, no valía poner solo el nombre de la BBDD sin más (cosa que si funcionaba en Win)

    Una cosita... Tu sabés que si al igual que en SQLite, ¿Mono-NHibernate funciona en SQLServer y/o Postgres?
    Haver yo hasta ahora no lo he conseguido pero creia que no podría con SQLite y lo conseguí.

    Saludos! y muchas gracias!

    David Benito
  • Jaja. Bueno, va mejorando, es verdad. Si pones el archivo sqlite3.dll en el directorio donde esta tu aplicación basta. Fijate que el error que te tira es que la tabla "personas" no existe.
  • David Benito
    Ahora tengo este fallo :(


    Unhandled Exception: NHibernate.ADOException: Could not save object ---> Mono.Da
    ta.Sqlite.SqliteException: Sqlite error
    no such table: personas
    at Mono.Data.Sqlite.Sqlite3.Prepare (System.String strSql, Mono.Data.Sqlite.Sq
    liteStatement previous, System.String& strRemain) [0x00000]
    at Mono.Data.Sqlite.SqliteCommand.BuildNextCommand () [0x00000] --- End of inn
    er exception stack trace ---

    at NHibernate.Impl.SessionImpl.SaveWithGeneratedIdentifier (System.Object obj,
    NHibernate.Engine.CascadingAction action, System.Object anything) [0x00000]
    at NHibernate.Impl.SessionImpl.Save (System.Object obj) [0x00000]
    at PruebaNHibernate.MainClass.Main (System.String[] args) [0x00000]


    Al menos la cosa cada vez pinta mejor...
    He colocado el sqlite3.dll y sqlite3.def en Windows/System32ç
    Nos leemos!
  • David Benito
    Ya se lo que es el GAC, digamos que donde puedo registrar assemblys sin necesitar de despues disponer de ellos en los binarios... Estoy mu equivocao??
  • David Benito
    Me da este error...


    Unhandled Exception: NHibernate.ADOException: cannot open connection ---> System
    .DllNotFoundException: sqlite3
    at (wrapper managed-to-native) Mono.Data.Sqlite.UnsafeNativeMethods:sqlite3_op
    en (byte[],intptr&)
    at Mono.Data.Sqlite.Sqlite3.Open (System.String strFilename) [0x00000]
    at Mono.Data.Sqlite.SqliteConnection.Open () [0x00000]
    at NHibernate.Connection.DriverConnectionProvider.GetConnection () [0x00000]
    at NHibernate.Impl.SessionFactoryImpl.OpenConnection () [0x00000] --- End of i
    nner exception stack trace ---

    at NHibernate.Impl.SessionFactoryImpl.OpenConnection () [0x00000]
    at NHibernate.Impl.ConnectionManager.GetConnection () [0x00000]
    at NHibernate.Impl.SessionImpl.get_Connection () [0x00000]
    at NHibernate.Transaction.AdoTransaction.Begin (IsolationLevel isolationLevel)
    [0x00000]

    ejecutando en Mono.
    Ahora me lo mirare mejor...
  • David Benito
    Buenas!
    Mmm...
    Entonces solo tengo que cambiar el binario de Mono.Data.Sqlite por una versión para windows??
    Donde lo encuentro el de version para windows??
    que es el GAC?
  • David, problema solucionado. Yo ya me había topado con esto cuando más tarde probé el código en Windows Vista. El assembly Mono.Data.Sqlite.dll difiere en la versión para GNU/Linux de la de Windows. Por eso, de tu instalación de Mono en Windows, buscá dicho assembly y reemplazalo en el directorio NHibernate.

    Con esto funciona tanto si lo ejecutás con MS .NET o con Mono bajo Windows. Hay una opción en NHibernate para indicar que busque el assembly en el GAC y no en el directorio actual. Esto sería mejor, así al distribuir tu aplicación para ambos SOs no tenes que estar armando paquetes diferentes.
  • David Benito
    Buenas,

    Las estoy ejecutando en Windows y en Mono (en la consola de Mono) en las dos, lo estoy haciendo desde Windows Vista. El caso es que cuando compilo en Mono (o Windows) y ejecuto en Win funciona perfectamente, pero al ejecutar en Mono se me queda buscando los drivers de MSSQL, pasando el log4net se me muere en este paso:

    ----
    2008-01-30 17:27:10,415 [1] DEBUG NHibernate.Connection.DriverConnectionProvider - Obtaining IDbConnection from Driver
    ----

    Bueno la cosa es que después de investigar, en otro foro, me dijieron que NHibernate y Mono no eran compatibles de momento... Se ve que enviaron un report a los de Mono, solucionaron el problemo pero se ve que no lo añadieron a la version 1.2.6.

    Bueno te dejo el hilo de la conversación del foro, por si tienes interés para que le eches un vistazo.

    http://groups.google.com.ar/group/NHibernate-Hispano/browse_thread/thread/a7e128f7ca8d946e

    Saludos!

    P.D: También lo he intentado en OpenSUSE con Mono, pero me salta una excepcion que me dice que no puede conectar con el servidor, tampoco he profundizado mucho.
  • No tengo mi PC acá, cuando la tenga hago unas pruebas y te contesto. Mientras, para aclararme unas cosas: vos dijiste en tu primer comentario que en Windows funciona, aunque no bajo Mono. A estas pruebas, ¿dónde y con qué las estas corriendo (no desarrollando)? ¿GNU/Linux y Mono? ¿Windows y Mono? ¿Qué versión de Mono? ¿Qué distro?
  • David Benito
    Buenas! y gracias por contestar.

    La Excepción que me salta es la siguiente:

    -------------

    Se generó la excepción NHibernate.ADOException en el programa:
    could not insert: [PruebaNHibernate.Persona#2][SQL: INSERT INTO personas (nombre, apellido, id) VALUES (?, ?, ?)]

    Execute()
    Flush()
    Commit()
    --------------

    y el contenido de la carpeta es esta:

    /nhiber_libero/app.config
    /nhiber_libero/AssemblyInfo.cs
    /nhiber_libero/data.db.sql
    /nhiber_libero/MonoDataSqliteDriver.cs
    /nhiber_libero/nhiber_libero.csproj
    /nhiber_libero/nhiber_libero.sln
    /nhiber_libero/Persona.cs
    /nhiber_libero/Persona.hbm.xml
    /nhiber_libero/Program.cs
    /nhiber_libero/sqlite3.exe
    /nhiber_libero/bin/Debug/Castle.DynamicProx y.dll
    /nhiber_libero/bin/Debug/data.db
    /nhiber_libero/bin/Debug/data.db-journal
    /nhiber_libero/bin/Debug/Iesi.Collections.dll
    /nhiber_libero/bin/Debug/log4net.dll
    /nhiber_libero/bin/Debug/Mono.Data.Sqlite.dll
    /nhiber_libero/bin/Debug/nhiber_libero.exe
    /nhiber_libero/bin/Debug/nhiber_libero.exe.config
    /nhiber_libero/bin/Debug/nhiber_libero.pdb
    /nhiber_libero/bin/Debug/NHibernate.dll
    /nhiber_libero/bin/Debug/sqlite3.dll

    Supongo que no tiene nada que ver pero estoy desarrollando el proyecto con SharpDevelop.

    Gracias por adelantado.
    David.
  • Hola David. Esa DLL va en la misma carpeta, ya que son los binarios nativos de SQLite, que tienen las funciones de bajo nivel. El provider de SQLite para .NET las utiliza.

    Ahora bien, ¿podes poner aquí la salida completa del programa y el contenido del directorio donde se encuentra la aplicación?

    Saludos!
  • David Benito
    Bueno, solucionado y nuevo fallo :(
    Tenia que poner la libreria sqlite3.dll dentro de la carpeta de binarios, a saber por que.
    Ahora me da un fallo a la hora de hacer el Commit de la transacción, en pocas palabras me pone que los valores del "insert" del registro no existen, cuando claramente se asignan en el objeto de la clase persisente como haces en el ejemplo...

    Bye Bye!
  • David Benito
    Buenas Milton!

    Estoy haciendo unas pruebas con NHibernate y Mono para el trabajo, debo decir que hasta el momento no me ha funcionado NHibernate bajo Mono en ninguna de las pruebas que he hecho, solo me ha funcionado ejecutandolo con win, al ejecutar las aplicaciones con Mono (ya sean compiladas con el framework .Net o Mono) se me queda colgao.

    He llegado a tu página de casualidad (googleando) :). He probado tu proyecto en Windows con SQLite y me da este error:

    Se generó la excepción NHibernate.ADOException en el programa:
    cannot open connection

    Begin()
    Begin()
    BeginTransaction()

    Bueno cualquier ayuda te lo agredeceria.
    Salud!
    En caso de que encontrará la solución lo haría saber por aquí.
blog comments powered by Disqus