2010-04-26 20 views
13

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

Respuesta

2

Por lo que vale, Sharp Architecture está haciendo más o menos exactamente lo que estás sugiriendo. Termina entregando una sesión por solicitud HTTP (más exactamente, una sesión por base de datos por solicitud HTTP). Su enfoque es ciertamente válido y también ofrece una sesión por solicitud. Prefiero el enfoque OO más limpio de SharpArch a través de DI sobre el uso de repositorios estáticos y la clase de ayuda.

+0

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

1

Hemos mezclado las aplicaciones ASP.NET/Windows Forms y la mejor solución que he encontrado es hacer la inyección de dependencia manual a través del constructor del repositorio. Es decir, cada clase de repositorio tiene un único constructor público que requiere una ISession. Esto permite que la aplicación tenga control completo sobre la unidad de trabajo y los límites de transacción. Es simple y efectivo. También tengo un conjunto de ayuda NHibernate muy pequeño que configura las fábricas de sesión y proporciona métodos para abrir una sesión regular o de contexto.

Hay muchas cosas que me gustan de S # arp Architecture y creo que vale la pena estudiar cómo funciona, pero me pareció demasiado arquitectónico para mi gusto.

+0

+1, también me pareció demasiado arquitectónico. Sin embargo, un repositorio estático es incluso más simple, por eso creo que ese es el camino a seguir. – Venemo

Cuestiones relacionadas