Pasé el resto de la tarde leyendo preguntas de StackOverflow y también algunas entradas de blog y enlaces sobre el tema. Todos ellos resultaron ser muy útiles, pero todavía siento que realmente no responden mi pregunta.¿Es un repositorio estático una forma correcta de usar NHibernate?
Por lo tanto, estoy desarrollando una aplicación web simple. Me gustaría crear una capa de acceso a datos reutilizable que luego pueda volver a utilizar en otras soluciones. El 99% de estos serán aplicaciones web. Esto parece ser una buena excusa para aprender NHibernate y algunos de los patrones que lo rodean.
Mis objetivos son los siguientes:
- no quiero la capa de lógica de negocio que saber nada sobre el funcionamiento interno de la base de datos, ni en sí NHibernate.
- Quiero que la capa de lógica de negocios tenga el menor número posible de suposiciones sobre la capa de acceso a datos.
- Quiero que la capa de acceso a datos sea lo más simple y fácil de usar posible. Este va a ser un proyecto simple, así que no quiero complicar demasiado cualquier cosa.
- Quiero que la capa de acceso a los datos sea lo menos intrusiva posible.
Teniendo todo esto en cuenta, decidí usar el patrón de repositorio popular. Leí sobre este tema en este sitio y en varios blogs de desarrollo, y escuché algunas cosas sobre el patrón de la unidad de trabajo.
También miré alrededor y comprobé varias implementaciones. (Incluyendo FubuMVC contrib, SharpArchitecture y material en algunos blogs). Descubrí que la mayoría de estos funcionan con el mismo principio: crean una "unidad de trabajo" que se ejemplifica cuando se crea una instancia de un repositorio, inician una transacción, hacer cosas y comprometerse, y luego comenzar todo de nuevo. Entonces, solo un ISession
por Repository
y listo. Luego, el código del cliente necesita instanciar un repositorio, hacer cosas con él y luego eliminarlo.
Este patrón de uso no satisface mi necesidad de ser lo más simple posible, así que comencé a pensar en otra cosa.
Descubrí que NHibernate ya tiene algo que hace que las implementaciones de "unidad de trabajo" personalizadas sean innecesarias, y esa es la clase CurrentSessionContext
. Si configuro correctamente el contexto de la sesión y hago la limpieza cuando sea necesario, estoy listo.
Por lo tanto, se me ocurrió esto:
que tienen una clase estática interna llamada NHibernateHelper
. En primer lugar, tiene una propiedad estática llamada CurrentSessionFactory
, que en la primera llamada crea una fábrica de sesiones y la almacena en un campo estático. (Uno ISessionFactory
por uno AppDomain
es lo suficientemente bueno). Luego, más importante aún, tiene una propiedad estática CurrentSession
, que comprueba si hay un ISession
vinculado al contexto de la sesión actual, y si no, crea uno, y lo vincula, y regresa con el ISession
vinculado al contexto de la sesión actual.
, ya que será utilizado principalmente con WebSessionContext
(así, uno ISession
por HttpRequest
, aunque para las pruebas de unidad, he configurado ThreadStaticSessionContext
), que debería funcionar sin problemas. Y después de crear y vincular un ISession
, enlaza un controlador de eventos al evento HttpContext.Current.ApplicationInstance.EndRequest
, que se encarga de limpiar el ISession
después de que finaliza la solicitud.(Por supuesto, solo hace esto si se está ejecutando realmente en un entorno web.)
Por lo tanto, con todo esto configurado, el NHibernateHelper
siempre será capaz de devolver un ISession
válido, por lo que no es necesario crear una instancia una instancia de Repositorio para que la "unidad de trabajo" funcione correctamente. En su lugar, el Repository
es una clase estática que opera con el ISession
de la propiedad NHibernateHelper.CurrentSession
, y expone la funcionalidad mediante métodos genéricos.
Así que, básicamente, terminé con dos singletons muy perezosos.
Tengo curiosidad, ¿qué piensas de esto? ¿Es una forma válida de pensar, o estoy completamente equivocado aquí?
EDIT:
que debe señalar que la clase NHibernateHelper es interna, así que prácticamente invisible para los consumidores del repositorio.
Otra idea es, para poder insertar una inyección de dependencia en la solución, hacer una interfaz llamada IDataProvider
, e instanciar una instancia de eso en la primera llamada a la clase Repository
. (Sin embargo, el código de la aplicación debe ser capaz de cuidar el concepto de contexto también.)
EDIT 2:
Parece que muchas personas como mi idea, pero todavía hay muy pocas opiniones al respecto en el respuestas
¿Puedo asumir que esta es una manera correcta de usar NHibernate, entonces? : P
Bueno, sí, pero creo que mi solución tiene una sintaxis un poco más fácil de usar, y definitivamente menos sobrecarga en términos de instanciación de objetos y, por lo tanto, uso de memoria. – Venemo