NHibernate timeout avec SQL Server

J'ai une application ASP.Net avec backend en C # qui utilise NHibernate avec SQL Server.

Récemment j'ai remarqué que pendant une longue période de time à faire certaines tâches dans une certaine page du web, il gèle et un timeout d'expiration arrive (exception NHibernate).

Après le problème de timeout je vais à SQL Server Management Studio et je peux voir dans le moniteur comment il y a des dizaines de process sans aucun état et tous à la même database:

Processus dans le moniteur SQL Server

J'ai cherché des solutions partout, et je ne sais pas si je suis probablement en train de me débarrasser de la session. Voici comment je dispose de la session:

public static void DisposeSession() { FlushSession(true); // Method that does a commit if there is a transaction ISession Session = CurrentSessionContext.Unbind(sessionFactory); if (Session != null) { Session.Close(); Session.Dispose(); } } 

Modifier 1:

J'utilise actuellement WebForms et il n'y a pas de sessions partagées entre les requêtes, les sessions sont éliminées correctement.

Le problème est que lorsque je commence à parcourir différentes parties de mon site Web (en faisant de nouvelles requêtes), les process commencent à se développer comme dans l'image … et à un certain point, la page répond avec une erreur d'exécution ou un timeout.

Comment puis-je contrôler ce comportement? Il est possible seulement d'avoir un process par request et lors de la disposition, la fermeture du process?

Édition 2:

J'avais tort, la gestion de la session est bien faite avec la méthode fournie dans la première réponse. Il y a des process mais ils sont correctement gérés par NHibernate.

Tout d'abord, assurez-vous que votre CurrentSessionContext ne partage pas la session entre les requests.

Généralement, ce type de context stocke la session dans le dictionary HttpContext.Current.Items . C'est un endroit sûr pour s'assurer qu'il ne sera pas partagé avec d'autres requêtes http.
Si à la place, il partage la session entre les requests, votre application échouerait pour la plupart des users une fois en charge.
S'il utilise un ThreadContext ou un CallContext , il échouera régulièrement pour certaines requêtes en cours de chargement, en raison de "l'agilité des threads ASP.Net" provoquant une request http pour changer de threads et perdre leur précédent ThreadContext et CallContext . HttpContext.Current.Items est garanti pour être préservé lorsqu'une requête http bascule les threads, pas les autres.

Si ce CurrentSessionContext semble correct, alors DisposeSession votre DisposeSession . Cela ne garantit pas que votre session sera fermée en cas d'échec du vidage.

Cela devrait probablement ressembler plus à:

 public static void DisposeSession() { try { FlushSession(true); // Method that does a commit if there is a transaction } finally { ISession Session = CurrentSessionContext.Unbind(sessionFactory); if (Session != null) { // Dispose closes the session too. And Close dispose the transaction // if there was one. And transaction Dispose rollbacks if it was pending. Session.Dispose(); } } } 

Ensuite, vérifiez que DisposeSession est toujours appelé quelle que soit la manière dont votre requête se termine. Vérifiez particulièrement ce qui se passe sur les requêtes déclenchant une exception. Cela inclut certains cas de redirection qui fonctionnent avec une ThreadAbortException , comme Response.Redirect("...") .

Gestion de session

A propos du pattern de gestion de session que j'utilise habituellement, je l'ai lié à l'dependency injections, avec un cycle de vie par requête et un module http assurant qu'il soit disposé quel que soit le résultat de la requête, avec une transaction traitée par un filter d'action.

Votre model est loin de cela. Si vous souhaitez le changer, vous pourriez avoir plus de facilité à suivre cette série de billets de blog d'un ancien consortingbuteur à NHibernate et auteur de NHibernate profiler.