Espacio de Dario Quintana

What are payday loans Payday Loans UK How much can you borrow

NHibernate Validator ready

Para los que todavía no sintonizaron NHibernate-Hispano, ayer di la noticia en este post de que se podía usar el nuevo port de NHibernate: NHibernate.Validator (port de este proyecto). Todavía no hay ejemplos y documentación así que por ahora, se puede reutilizar lo que hay disponible en Java.

Links:

NHibernate committer

Ahora soy parte del NHibernate Team! Ayer a la noche me hicieron la bienvenida en la dev-list, lo cual me pone muy contento. Gracias principalmente a Fabio Maulo y Karl Chu (nuevo líder de NHibernate) por esta oportunidad.

El plan a corto plazo es portar Hibernate Validator y después creo que Fabio ya tiene pensado asignarme algunas tareas :D

Aprovecho para contar que NHibernate Validator ya tiene varias clases portadas/implementadas; la clase más importante (ClassValidator) está portada en un 70 %. En cuanto tenga más detalles lo haré saber por aquí mismo.

NHibernate + EventListeners + "Cualquier Framework de Validación"

En este post estaba adelantando algo que estoy empezando a hacer, por ahora bosquejando y pensando, sin embargo…hay algo funcional para ir pispeando.

La idea es crear un "puente" entre NHibernate y diferentes frameworks para validar nuestras entidades de negocio. Hay quienes les gusta validar solamente en la entrada, otros en la capa de negocio, otros en la capa de acceso a datos, u otros en todos lados! Este "approach" intentará validar en la capa de Acceso a datos, justo antes de que NHibernate realice un Save/Update (y por que no un Delete?).

Por ahora, pueden encontrar el código disponible para usar haciendo un checkout de SVN de uNHAddIns. Consta de un proveedor para usar el validador del Enterprise Library Application Block . Después veremos que otros frameworks podemos inyectar (para eso necesito sus sugerencias).

Como pueden ver en este test, NHibernate arroja una excepción si alguien intenta guardar una entidad no válida. Créanme que arroja luz verde.

[Test,ExpectedException(typeof(ValidationException))] public void InsertWithInvalidEntity() { using (ISession s = sf.OpenSession()) { using (ITransaction tx = s.BeginTransaction()) { s.Save(GetNoValidFoo()); tx.Commit(); } } }

Para poder configurar este escenario es necesario una configuración previa como esta:

cfg = new Configuration(); cfg.SetProperty(Environment.HibernateValidationProvider, typeof(EntLibValidator).AssemblyQualifiedName); ValidateEventListener validateEventListener = new ValidateEventListener(); cfg.SetListener(ListenerType.PreInsert, validateEventListener); cfg.SetListener(ListenerType.PreUpdate, validateEventListener); cfg.Configure(); sf = cfg.BuildSessionFactory();

El EventListener ValidateEventListener hace el trabajo de intercepción antes de las operaciones Insert/Update, de ese modo es como podemos hacer el trabajo de validación.

Esto es un borrador, que por cierto funciona, así que puede cambiar. Todo comentario es más que bienvenido.

Para hacer checkout de el código fuente:

http://unhaddins.googlecode.com/svn/branches/NHTrunk/

NHibernate – Bulk Manipulation with SQL Native

Hace unos días atrás Fabio Maulo hice este anuncio (como siempre lo hace) en NHibernate-Hispano hablando sobre esta nueva característica disponible ya en el trunk de NHibernate: Bulk Manipulation.

Por ahora esta característica solamente funciona con SQL Nativo y aquí tenemos un ejemplo:

using (ISession s = sf.OpenSession()){ using(ITransaction tx = s.BeginTransaction()){ s.CreateSQLQuery("update Book set Price = Price*1.1") .ExecuteUpdate(); tx.Commit(); }

O así:

using (ISession s = sf.OpenSession()){ using(ITransaction tx = s.BeginTransaction()){ s.CreateSQLQuery("update Book set Price = Price*:increase") .SetDecimal("increase",1.1m) .ExecuteUpdate(); tx.Commit(); }

O de esta manera:

using (ISession s = sf.OpenSession()){ using(ITransaction tx = s.BeginTransaction()){ s.GetNamedQuery("change-book-price") .SetDecimal("value",1.1m) .ExecuteUpdate(); tx.Commit(); }

Y la named query para la última consulta es:

<sql-query name="change-book-price"> update Book set Price = Price*:value </sql-query>

Uno de los principales escenarios donde se presenta una desventaja de los ORM es que necesitan tener en memoria a todos los objetos que necesitan modificar, una modificación en masa. Ahora no es necesario hacer esto, se puede usar esta funcionalidad sin mayores complicaciones.

El ejemplo muestra a una simple entidad Book (libro) que además tiene una propiedad Price (precio). El update masivo muestra como actualizar la property Price de todas las entidades aumentando un 10 %.

Analyzers en Lucene.Net

En este post estábamos viendo la integración de Lucene.Net con NHibernate mediante NHibernate Search.

Lucene puede indexar texto desde muchas fuentes: PDF, HTML, Documentos de Word entre los más conocidos y esto es lo que hace a Lucene muy usado por muchas aplicaciones reales para solucionar problemas de búsqueda. Luego que Lucene parsea los documentos desde un medio rico, debe convertir este stream en un formato de tokens de texto plano para que los pueda digerir y así indexar el contenido. El paso previo a la indexación es el análisis, y para esto se utilizan Analyzers. Lucene provee algunas clases que se pueden utilizar por ejemplo: WhitespaceAnalyzer que se encarga de tokenizar el texto sin tener en cuenta los espacios en blanco; StopAnalyzer que elimina las StopWords en Inglés del texto para poder indexarlo, por ejemplo: the, an, a, that, this, entre otras.

Usando NHibernate Search, podemos realizar consultas contra los índices que mantiene Lucene, ya sea en Memoria o en el propio sistema de archivos. Este es un ejemplo de una consulta usando NHibernate Search:

QueryParser qp = new QueryParser("Summary", new StopAnalyzer()); IQuery NHQuery = s.CreateFullTextQuery(qp.Parse("series"), typeof(Book)); IList result = NHQuery.List();

QueryParser recibe como parámetro un Analyzer, en este caso StopAnalyzer. Utilizando este Analyzer, Lucene encuentra los términos de búsqueda dentro del texto de búsqueda. Esto no tiene nada que ver con el Analyzer que se configura Lucene al comienzo, que indica la manera en que se van a filtrar los tokens que van almacenarse al Index. Este analyzer realiza un filtro en el string de búsqueda para encontrar las keywords de referencia a buscar.

Para entender un poco más sobre los Analyzer, realicé esta aplicación de consola basado en los ejemplos en Java de Lucene In Action, bueno… en realidad solo fue una traducción de Java a C# de los ejemplos que había. La idea es probar que tokens de salida producen distintos Analyzers ante una entrada de texto:

En este ejemplo utilicé dos analyzer de Lucene y uno personalizado a unas cuantas Stop Words del Español:  SpanishStopAnalyzer. El programa que utilicé para correr ejemplo pueden hacer un checkout de aquí.

NHibernate Search

English post

Una de las características nuevas de NHibernate portadas de Hibernate 3.2 es NHibernate Search. Lucene es el motor de búsqueda de textos usado por NHibernate que permite a las aplicaciones a realizar consultas sobre texto almacenado. Esta característica está disponible en NHibernate 1.2.1 o en NHibernate 2.0 (versión del SVN).

El ejemplo de NHibernate Search con NHibernate 2.0 está disponible para la descarga aquí:

NHibernate Search Demo

Para poder hacer búsquedas sobre el texto de nuestras entidades debemos decorar nuestros objetos de negocio con algunos atributos como se muestra aquí:

using NHibernate.Search; using NHibernate.Search.Attributes; [Indexed] public class Book { private string author; private int id; private string name; private string summary; public Book() { } public Book(int id,string author, string name, string summary) { this.id = id; this.author = author; this.name = name; this.summary = summary; } [DocumentId] public virtual int Id { get { return id; } set { id = value; } } [Field(Index.Tokenized, Store = Store.Yes)] public virtual string Author { get { return author; } set { author = value; } } [Field(Index.Tokenized, Store = Store.Yes)] public virtual string Summary { get { return summary; } set { summary = value; } } [Field(Index.Tokenized, Store = Store.Yes)] public virtual string Name { get { return name; } set { name = value; } } }

No se puede realizar la configuración vía el archivo hibernate.cfg.xml todavía. La configuración debe lucir como se muestra abajo. Hay unos pasos adicionales a tener en cuenta a la hora de configurar NHibernate Search en nuestra aplicación.

cfg = new Configuration(); cfg.SetProperty("hibernate.search.default.directory_provider", typeof(RAMDirectoryProvider).AssemblyQualifiedName); cfg.SetProperty(NHibernate.Search.Environment.AnalyzerClass, typeof(StopAnalyzer).AssemblyQualifiedName); cfg.Configure(); sf = cfg.BuildSessionFactory(); SearchFactory.Initialize(cfg, sf);

Creé 3 libros (Book) para poder hacer este ejemplo funcional:

using (IFullTextSession s = Search.CreateFullTextSession(sf.OpenSession(new SearchInterceptor()))) { using(ITransaction tx = s.BeginTransaction()){ Book b1 = new Book(1, "Eric Evans", "Domain-Driven Design: Tackling Complexity in the Heart of Software", @"This book provides a broad framework for making design decisions and a technical vocabulary for discussing domain design. It is a synthesis of widely accepted best practices along with the author's own insights and experiences." ); s.Save(b1); Book b2 = new Book(2, "Pierre Kuate", "NHibernate in Action", @"In the classic style of Manning's 'In Action' series, NHibernate in Action introduces .NET developers to the NHibernate Object/Relational Mapping tool. As NHibernate is a port of Hibernate from Java to .NET."); s.Save(b2); Book b3 = new Book(3, "John Doe", "Foo book NHibernate", "Foo series book"); s.Save(b3); s.Flush(); tx.Commit(); } }

Realizamos algunas consultas de texto sobre este escenario. El ejemplo a continuación es utilizando la interfase IQuery. El motor de búsqueda de texto tratará de encontrar la palabra "series" en las propiedad Summary.

using (IFullTextSession s = Search.CreateFullTextSession(sf.OpenSession(new SearchInterceptor()))) { QueryParser qp = new QueryParser("id", new StopAnalyzer()); IQuery NHQuery = s.CreateFullTextQuery(qp.Parse("Summary:series"), typeof(Book)); IList result = NHQuery.List(); Debug.Assert(result.Count == 2); }

Y este ejemplo a continuación es usando Criteria. El ejemplo trata de encontrar el texto "NHibernate" en las propiedades Summary (resume) y Name (nombre del libro)

using (IFullTextSession s = Search.CreateFullTextSession(sf.OpenSession(new SearchInterceptor()))) { IList result = s.CreateCriteria(typeof(Book)) .Add(Search.Query("Summary:NHibernate or Name:NHibernate")) .List(); Debug.Assert(result.Count == 2); }

Como se puede apreciar, para realizar las búsquedas se debe usar la interfase  IFullTextSession en vez de las conocidas hasta el momento ISession o IStatelessSession.

Por un Framework para hacer BPN

Estuve jugando un poco en un framework para hacer BPN (BackPropagation Networks). Todavía sigo en etapa de diseño e implementación, así que llevará su tiempo para que esté completamente operacional.

Que le podríamos pedir a un framework similar? Estuve bosquejando como se vería el aprendizaje y convergencia de la red y salió algo similar:

Configuration cfg = new Configuration(); cfg.SetLearningRate(0.2); cfg.SetMomentRate(0.1); cfg.SetPatternError(0.001); cfg.AddNeuronsAtInput(4); //4 inputs cfg.AddHiddenNeuronsAt(1,5,typeof(SigmoidalNeuron)); // 1srt level: 5 neurons cfg.AddHiddenNeuronsAt<SigmoidalNeuron>(2, 6); // 2nd level: 5 neurons cfg.AddNeuronsAtOutput(5,typeof(SigmoidalNeuron)); //5 Outputs IList<Pattern> patterns = GetPatterns(); cfg.SetPatterns(patterns); Bpn bpn = cfg.BuildNetwork(); while (bpn.Propagate()) { //do something in the middle of the step }

La función Propagate() indicaría un paso en la propagación de todos los patrones; esto correspondería con la propagación hacia adelante de 1 patrón, la propagación hacia atrás de los errores y la corrección de los pesos de la red (el aprendizaje). El bucle continuaría hasta que el error se sea menor que el Epsilon (Error por patrón) que hemos establecido con anterioridad en todos los patrones.

Algunas clases:

Pueden ir mirando el código del proyecto aquí, hay algunas pruebas e implementaciones hechas. Cualquier pregunta, duda o colaboración será bienvenida.