7
votes

Gestion des transactions NHibernate dans ASP.NET MVC - Comment cela devrait-il être fait?

J'écris un simple ASP.NET MVC à l'aide de la session par demande et par transaction par modèles de demande (httpmodule personnalisé). Il semble fonctionner correctement, mais .. La performance est terrible (une simple page de page ~ 7 secondes). Pour chaque demande HTTP, des ressources graphiques incluant (toutes les images du site) une transaction est créée et qui semble retarder les temps de chargement (sans les délais de chargement des transactions par image sont ~ 1-10 ms avec transactions qu'ils ont plus de 1 seconde) . Quel est le moyen approprié de gérer les transactions dans la pile ASP.NET MVC + NH?

Lorsque j'ai mis toutes les transactions dans mes méthodes de référentiel, certaines raisons obscures, j'ai obtenu une "transaction implicite" à NHProf (les instructions SQL ont été exécutées en dehors de la transaction, même dans la session de code.Save () / Mise à jour () / etc Modes ont été invoqués dans la transaction "en utilisant" la portée et avant la transaction.commit () appels) BTW sont des transactions implicites vraiment mauvaises?


2 commentaires

Pourquoi activez-vous des transactions pour des opérations de lecture?


@Dave Swersky parce que c'est la meilleure pratique de toujours utiliser des transactions, que vous lisiez ou que vous économisez. Voir NHProfrof.com/learn/alerts/DonotueUnplicitTransactions pour plus d'informations.


3 Réponses :


4
votes

Les transactions implicites se produisent lorsque vous ne placez pas vos déclarations dans une transaction. L'implicite est que si vous ne déclarez pas explicitement une transaction, chacune de vos déclarations fonctionne dans sa propre transaction. Alors oui c'est mauvais. ce mauvais ? Je ne sais pas assez sur ce que vous travaillez à juger.

Je fais la même chose que vous faites avec la session par demande, mais je ne reçois nulle part près des mêmes numéros de performance. Je recommanderais de regarder en tournant le log4net pour NHibernate et de voir ce que ça fait. Votre demande ne devrait créer que l'usine de session et les usines de proxy une fois (la gestion de l'usine de session serait l'un des rares endroits où j'utiliserais un singleton). C'est vraiment la seule chose que je puisse penser cela pourrait le causer.


1 commentaires

Merci pour l'indice, SéditionFactory n'est cependant créé qu'une fois dans la vie de l'application.



4
votes

Il y a quelques problèmes ici:

Tout d'abord, en ce qui concerne vos problèmes de performance. Assurez-vous que l'IsessionFactory n'est pas instancié une fois? C'est un objet très coûteux de créer, ce qui devrait probablement être un singleton dans votre application Web créée sur Application_Start, plutôt que dans Application_BeGinRequest. Je suppose que vous obtenez une telle performance médiocre est que vous créez une nouvelle iSSessionFactory par demande plutôt qu'une fois pour l'application complète.

Deuxièmement, en ce qui concerne les transactions implicites, ils ne sont pas que mauvais, mais à partir de la manière dont vous décrivez votre code, vous ne devriez pas recevoir ces erreurs. Êtes-vous sûr que vous exécutez vos appels dans une transaction? Il est possible que vous accédez à certaines propriétés de chargement paresseuse des pages .aspx et .ascx qui peuvent exécuter en dehors de votre transaction.


1 commentaires

IsessionFactory est instancié une seule fois, il semble que invoquer la session.begintransaction () prend jusqu'à 1 à 2 secondes parfois: / telle donc ce qui provoque une mauvaise performance. J'utilise le serveur PostgreSQL en cours d'exécution sur Linux .. Hmm peut-être que je vais tester avec une autre dB ou essayer une approche qui utilise ActionFilters pour la gestion des transactions.



3
votes

Vous devez utiliser une session contextuelle de sorte qu'une nouvelle session et une nouvelle transaction ne soient pas créées sur chaque demande de ressource image, etc. Voir ma réponse à Cette question . Ce changement devrait améliorer considérablement les performances. C'est probablement aussi la cause fondamentale des avertissements implicites de transaction.

Un autre problème de performance fréquent avec les applications NH utilise log4net avec un niveau de débogage.

EDIT: Les réponses de Min et Kevin Pang sont également de bons conseils afin que je ne me dérangerai pas de répéter leurs déclarations.


2 commentaires

Les sessions contextuelles sont très susceptibles de résoudre mon problème, mais je ne sais toujours pas quand devrais-je commencer la transaction?


Vous pouvez commencer et mettre fin à la transaction dans votre httpmodule, c'est une approche raisonnable à mon avis. Je voudrais d'abord implémenter des sessions contextuelles et voir si vous avez toujours un problème de performance avant de regarder ailleurs. Je préfère gérer la transaction sur la page afin que je puisse répondre aux exceptions "mieux".