Como ya dije antes, los problemas de instalación de SQL Express 2005 nos han llevado a probar bases de datos embebidas, y una de ellas es Sql Server CE. En las primeras pruebas que hemos realizado con esta base de datos, hemos encontrado algunos problemillas. Uno de ellos ha sido a la hora de almacenar en la base de datos campos de tipo NTEXT
o IMAGE
.
Dejando de lado si realmente es una buena idea almacenar columnas de gran tamaño (NTEXT
, IMAGE
, …) en una base de datos como SQL CE, en nuestro caso era importante poder hacerlo. A priori todo tenía buena pinta y el esquema de base de datos se generaba correctamente con las columnas del tipo configurado en los mappings. Sin embargo, al ejecutar los tests de integración (que en estas pruebas han demostrado con creces su utilidad) descubrimos algunos fallos porque se truncaban los datos introducidos en la base de datos.
Tras investigar un poco y encontrar más gente con este problema, vimos que era necesario modificar el comportamiento de NHibernate.
Por fortuna, NHibernate ofrece multitud de puntos de extensión, por lo que la solución es sencilla: basta con crear un nuevo driver para Sql Server CE que gestione correctamente este tipo de columnas. El resultado final es tan simple como esto:
public class SqlCeDriver : SqlServerCeDriver { protected override void InitializeParameter(IDbDataParameter dbParam, string name, SqlType sqlType) { base.InitializeParameter(dbParam, name, sqlType); if (sqlType is StringClobSqlType) { ((SqlCeParameter)dbParam).SqlDbType = SqlDbType.NText; } else if (sqlType is BinaryBlobSqlType || (sqlType is BinarySqlType && sqlType.Length > 8000)) { ((SqlCeParameter)dbParam).SqlDbType = SqlDbType.Image; } } }
Una vez creado este nuevo Driver, es necesario configurar NHibernate para que lo utilice:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" > <session-factory> <property name="connection.driver_class">My.Namespace.SqlCeDriver, MyAssembly</property> <property name="dialect">My.Namespace.SqlCeDialect, MyAssembly</property> <property name="connection.connection_string">data source = data.sdf</property> <property name="connection.provider">My.Namespace.SingleConnectionProvider, MyAssembly</property> <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property> </session-factory> </hibernate-configuration>
Como se puede ver en la línea 4, hay que indicar el nombre completo de la clase que implementa el driver. Además, hay otras personalizaciones (las líneas en las que aparecen referencias a MyAssembly
), de las que hablaré más adelante.
Pingback: SQL Server CE y NHibernate: Mantener la conexión abierta | Koalite's blog
Gracias Juan!. Excelente, estuve un rato largo intentando otras soluciones hasta que encontre la tuya que anda perfecto.
Para los nuevos en nHibernate como yo, hay que agregar los namespaces y referencias a las dll.
using System.Data.SqlServerCe;
using NHibernate.Driver;
using NHibernate.SqlTypes;