2008-10-05 19 views
11

estoy desarrollo y aplicación que se ejecuta como un servicio de Windows. Existen otros componentes que incluyen algunos servicios WCF, una GUI de cliente, etc., pero es el servicio de Windows el que accede a la base de datos.NHibernate gestión de sesiones en aplicaciones de servicio de Windows

Por lo tanto, la aplicación es un servidor de larga duración, y me gustaría mejorar su rendimiento y escalabilidad, que estaba buscando para mejorar el acceso de datos, entre otras cosas. Publiqué en otro hilo sobre el almacenamiento en caché de segundo nivel.

Este post es sobre la gestión de sesiones para el hilo de larga duración que tiene acceso a la base de datos. ¿Debo utilizar un contexto estático de subprocesos? Si es así, ¿hay algún ejemplo de cómo se implementaría?

Cada uno alrededor de la red que está utilizando NHibernate parecen estar muy centrado en las arquitecturas de estilo de aplicaciones web. Parece haber una gran falta de documentación/discusión para diseños de aplicaciones que no sean web.

Por el momento, mi largo hilo conductor hace esto:

  1. Llamada 3 o 4 métodos DAO
  2. Verificar el estado de los objetos separados regresó.
  3. Actualice el estado si es necesario.
  4. Llame a un par de métodos DAO para conservar las instancias actualizadas. (pase el ID del objeto y la instancia en sí; el DAO recuperará el objeto del DB nuevamente y establecerá los valores actualizados y session.SaveOrUpdate() antes de confirmar la transacción.
  5. Sleep for 'n' seconds
  6. !
  7. Repetir todo de nuevo

por lo tanto, el siguiente es un patrón común que utilizamos para cada uno de los métodos DAO:

  • sesión abierta usando sessionFactory.openSession()
  • iniciar la transacción
  • Do db work. recuperar/actualizar etc
  • Commit trans
  • (Rollback en caso de excepciones)
  • Por último siempre disponer de transacciones y session.close()

Esto sucede por cada llamada de método a una clase DAO . Sospecho que esto es una especie de anti-patrón de la forma en que lo estamos haciendo.

Sin embargo, no soy capaz de encontrar suficiente dirección en cualquier lugar en cuanto a cómo podemos mejorarlo.

Nota: mientras este hilo se ejecuta en segundo plano, haciendo sus cosas, hay solicitudes provenientes de los clientes de WCF cada una de las cuales podría hacer 2-3 llamadas DAO - a veces consultando/actualizando los mismos objetos por mucho tiempo hilo conductor trata con.

Cualquier ideas/sugerencias/consejos para mejorar nuestro diseño será apreciado considerablemente. Si podemos conseguir una buena discusión va, podríamos hacer de esto una wiki de la comunidad, y possbily vincular a aquí de http://nhibernate.info

Krishna

Respuesta

7

Parece que hay una gran falta de documentación/discusión de la no diseños de aplicaciones web.

Esta también ha sido mi experiencia. Sin embargo, el modelo que estás siguiendo me parece correcto. Siempre debe abrir una sesión, confirmar cambios y luego cerrarla nuevamente.

+1

+1. He visto este consejo general varias veces: SessionFactory es costoso. Solo créelo una vez. Las sesiones son baratas. – snicker

0

Acepto, no hay muchos ejemplos de aplicaciones con estado. Estoy pensando en hacer lo siguiente:

Como usted, tengo un servicio de Windows que aloja varios servicios de WCF. Entonces los servicios de WCF son los puntos de entrada. En última instancia, todos mis servicios WCF heredan de AbstractService, que maneja una gran cantidad de registros e inserciones/actualizaciones básicas de base de datos.

En uno de los mejores puestos de NHibernate que he visto, un HttpModule hace lo siguiente: ver http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx

private void BeginTransaction(object sender, EventArgs e) { 
    NHibernateSessionManager.Instance.BeginTransaction(); 
} 
private void CommitAndCloseSession(object sender, EventArgs e) { 
    try { 
     NHibernateSessionManager.Instance.CommitTransaction(); 
    } 
    finally { 
     NHibernateSessionManager.Instance.CloseSession(); 
    } 
} 

Así que tal vez debería hacer algo similar en AbstractService. Entonces efectivamente terminaré con una sesión por invocación de servicio. Si examina el enlace de artículo sobre mejores prácticas de NHib que aparece arriba, verá que el NHibernateSessionManager debería ocuparse de todo lo demás, siempre que abra y cierre la sesión (constructor y destructor de AbstractService).

Solo un pensamiento. Pero estoy experimentando errores debido a que mi sesión parece estar dando vueltas por mucho tiempo, y estoy obteniendo el infame error - NHibernate.AssertionFailure: null id en la entrada (no descargue la sesión después de que ocurra una excepción).

0

También puede vaciar la sesión sin realmente cerrarla y logra lo mismo. Hago.

1

Esta pregunta ya es un poco vieja, pero otra técnica sería usar Sesiones Contextuales en lugar de crear una nueva sesión en cada DAO.

En nuestro caso, estamos pensando en crear la sesión una vez por hilo (para nuestro servicio win32 de subprocesos múltiples) y ponerla a disposición de los DAO utilizando una propiedad que devuelva SessionFactory.GetCurrentSession() (utilizando ThreadContext proveedor de sesión actual, por lo que es sesión-por-hilo) o vía DI (inyección de dependencia - otra vez usando ThreadContext.)

More info on GetCurrentSession and Contextual Sessions here.

0

Recientemente hemos comenzado a usar un contenedor IoC para administrar el ciclo de vida de la sesión, como reemplazo de las sesiones contextuales mencionadas anteriormente. (Más detalles here).

Cuestiones relacionadas