Posts anteriores: | Empezando con NHibernate |
De aquí en más, cuando haga referencia a NHibernate (NH), usaré NH2.1.0.
NH es un framework muy flexible y por ese motivo la configuración de la session-factory es bastante extensa; sin embargo nadie nos obliga a usar o definir un valor para todas las features suportadas por NH. Acá les muestro la configuración que uso para mis cursos de introducción a NHibernate:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="StartingNH">
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="connection.connection_string_name">StartingNH</property>
<property name="connection.isolation">ReadCommitted</property>
<property name='proxyfactory.factory_class'>
NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu
</property>
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
<property name="adonet.batch_size">50</property>
<property name="command_timeout">10</property>
<property name="format_sql">true</property>
</session-factory>
</hibernate-configuration>
Esta configuración puede ser usada tranquilamente en producción. Para su entorno de desarrollo, tal vez, sea mejor usar la propiedad connection.connection_string en lugar que user connection.connection_string_name.
En realidad una configuración perfectamente valida es:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="connection.connection_string">
Data Source=localhost\SQLEXPRESS;Initial Catalog=BlogSpot;Integrated Security=True
</property>
<property name='proxyfactory.factory_class'>
NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu
</property>
</session-factory>
</hibernate-configuration>
Como verán son tres las cosas que NH necesita para poder funcionar:
- El Dialect del RDBMS que vamos a usar (y hasta eso es opciónal pero bueno…)
- La connection string
- El sistema de DynamicProxy que usará para trabajar en forma transparente con lazy-loading.
No me digan que esa es una configuración compleja.
Hay otra parte de la configuración que, no es de NH pero, es importante en fase de desarrollo/tests: la configuración de log4net.
Acá va una muestra:
<log4net debug="false">
<appender name="console" type="log4net.Appender.ConsoleAppender, log4net">
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<appender name="CleanConsole" type="log4net.Appender.ConsoleAppender, log4net">
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%m%n" />
</layout>
</appender>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender,log4net" >
<param name="File" value="NHibernateLog.txt" />
<param name="AppendToFile" value="false" />
<param name="RollingStyle" value="Date" />
<param name="DatePattern" value="yyyy.MM.dd" />
<param name="StaticLogFileName" value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<root>
<priority value="WARN" />
<appender-ref ref="RollingFile" />
</root>
<logger name="NHibernate.SQL">
<level value="OFF" />
</logger>
<logger name="NHibernate.Tool.hbm2ddl.SchemaExport">
<level value="ERROR" />
</logger>
</log4net>
Para quien no conoce log4Net aclaro que lo que está siempre activo son dos niveles de log: el WARN (warning) y el ERROR para el SchemaExport que es para quien usamos NH tambien para generar el DB schema en fase de tests.
Las recomandaciones para NH
- Eviten usar frameworks que "ocultan" la configuración de NH; enrollar un XML con otro XML no tiene sentido (hasta que alguien demuestre lo contrario).
- Si quieren usar algún framework que permita la configuración por codigo asegurense que lo haga heredando de NHibernate.Cfg.Configuration y/o usando una implementación de IHibernateConfiguration y no generando otro XML.
- Nombren la/las session-factory especialmente si trabajan en multi-rdbms. El nombre de la session-factory puede ser la key para encontrar la session-factory asociada a un determinado DAO/Repository.
- Definan siempre el isolation level aunque cada Drive tenga ya su default; los valores admitidos son definidos en System.Data.IsolationLevel.
- Usen el tag <mapping> para agregar sus mappings a una configuración.
- No olviden definir query.substitutions; evitarán sorpresas cuando ejecuten HQLs en donde especifiquen valores de clases (true,false) y no valore de DB (1 o 0).
- Si saben que su drive suporta la ejecución de queries en batch (más de un queries en un solo round-trip) definan adonet.batch_size; si no lo definen el batcher no se activa y la diferencia en performance puede ser notable.
- Definan el command_timeout (en segundos) a un valor congruo para su aplicación; en mi forma de endender si un comando SQL lleva mas de 10 segundos algo anda mal.
- Controlar alguna SQL generada por NH puede ser un desafió no de poco (especialmente cuando le toman la mano al ORM). Configurar format_sql a true le permitirá ver las SQL en un formato mas human-readable (NO todo en una sola linea).
- En desarrollo usen el file hibernate.cfg.xml y una base de datos local y no usen el App.config y base de datos común para los tests; cada desarrollador tiene el derecho de tener la base en local con su connection-string y hacer debug sin preocuparse de bloquear a los otros desarrolladores. El file hibernate.cfg.xml tendrá que ser excluido del repository de fuentes (svn:ignore) mientras que se puede incluir un file hibernate.cfg.template para que cada desarrollador tenga un ejemplo.
- No activen la cache (aka second level cache) hasta que la applicación no tenga por lo menos una versión en producción. La cache no es la panacea de las performance; una applicación debe funcionar bien sin cache… luego le pondrán el “turbo” si y donde lo necesita.
Las recomandaciones para el logging
- No olviden configurar el logging de NHibernate.
- Ya que lo tendrán activo no olviden leerlo; en NH nos costó bastante definir algunos niveles de log y si se loguea un WARNING, en casi todos los casos, es porque hay que prestar attención a algo que está pasando. Ni hablar si el log es un ERROR.
- Cuando escriban behavior-tests, con o sin WatIn, activen el log “NHibernate.SQL” a DEBUG y miren las SQL que NH está generando. Este proceso es indispensable en fase de optimización de la applicación.
- Por lo mismos motivos del file de configuración de NH usen un file tambien para la configuración de log4net (no usen el App.config) y escluyan ese file del repository de fuentes; cada desarrollador tiene el derecho de activar los logs que necesite.
No comments:
Post a Comment