J'ai lu la documentation et expliqué pourquoi il est fortement recommandé d'utiliser des transactions sur des opérations de lecture dans NH. Cependant, je n'ai pas encore totalement "acheté" dedans. Est-ce que quelqu'un peut essayer de l'expliquer sans me dire quoi que ce soit à RTFM, ce que j'ai déjà fait? ;)
Réponses
Trop de publicités?Ce post à partir de l'un des auteurs peut-être votre réponse:
Même si nous sommes seulement à la lecture des données, nous souhaitez utiliser une transaction, car à l'aide d'une transaction de s'assurer que nous obtenons un résultat cohérent à partir de la base de données. NHibernate supposer que tous les accès à la base de données est effectuée en vertu d'un transaction, et à déconseiller fortement toute utilisation de la session sans des transactions.
En laissant de côté la question de la sécurité de travailler avec les transactions, les l'hypothèse que les opérations sont coûteux et nous avons besoin d'optimiser leur est un faux. Comme déjà mentionné, les bases de données sont toujours en cours d'exécution dans des transactions. Et bases de données ont été fortement optimisé pour fonctionner avec les des transactions. La question est de savoir ce que c'est par déclaration ou par lot. Il ya une certaine quantité de travail qui ont besoin d' à faire pour créer et disposer d'une de transaction, et d'avoir à le faire par la déclaration est effectivement plus coûteux que le faire par lot.
Ce que les autres ont dit, c'est vrai, mais ils n'ont pas souligné que le problème de ne pas contrôler les transactions de vous-même, c'est que si vous effectuez plusieurs NHibernate opérations sans une transaction explicite, chacune de ces opérations auront lieu dans les transactions distinctes.
Donc, vous pouvez facilement obtenir une incohérence entre les opérations. En faisant explicitement le départ d'une NHibernate transaction puis d'effectuer les opérations, vous avez la garantie de la cohérence dans l'ensemble de ces opérations.
C'est vrai, bien sûr, pour TOUTE couche d'accès aux données qui, implicitement, commence transactions pour vous si vous n'avez pas. Il n'est pas limité à NHibernate.
var fooIdFromDb = ExecuteQuery("Select Id from Foo where something = somethingelse");
var barsFromDb = ExecuteQuery("Select * from Bar where FooId = " + fooIdFromDB);
Que se passe-t-il si une autre transaction supprime les lignes de Bar entre les deux requêtes? Vous aurez des problèmes avec les données fantômes. Ce n'est pas un problème spécifique à NHibernate. Vous aurez le même problème avec tout autre type d'accès à la base de données sans utiliser de transactions. Vous devriez lire le manuel sur les transactions en général au lieu du manuel NHiberante.
Concentrons-nous sur ce qui se passe si vous ne pas utiliser les transactions. Il est de coutume, mais pas obligatoire, que vous fermez la Session à la fin du traitement, mais avant de commencer la lecture des données (c'est à dire, la Vue). Cette méthode est propagé sous le terme "Open Session in View" (même s'il a évidemment un modèle pour la prévention de la lire avant de fermer). Ce modèle est souvent utilisé dans une application web où la session est ouverte lorsque la demande arrive et fermé juste avant l'écriture du flux de la réponse.
(N)Hibernate a besoin d'une séance et une opération. Quand vous lisez sans l'aide d'une transaction explicite, la transaction sera configuré pour vous. Quand vous lisez après une transaction est validée, le comportement dépend de NH configuration et le pilote.
Les deux ODBC et JDBC ne définissent pas ce qui se passe quand une connexion est fermée et il n'y a non validées ou unrollbacked de données. Lorsque la connexion est rouvert, il est possible qu'une nouvelle transaction est automatiquement démarré.
À l'aide de non-accès transactionnel ne peut être utilisé conjointement avec le paramètre auto-commit
explicitement dans le NHibernate de configuration. Si non, la valeur par défaut du pilote est utilisé et il peut fonctionner, ou peut ne pas fonctionner.
En bref, il y a de nombreuses lacunes et des comportements indéfinis lorsque vous n'utilisez pas de transactions sur le lit. Il travaillera souvent, mais cela dépend de la configuration, les modèles, les pilotes. Il y a de grandes chances que vous ayez LazyInitializationException
s, ce qui est un résultat commun de lire après s'engager sans l'ouverture d'une nouvelle transaction.
La "meilleure pratique" consiste à utiliser une opération de lecture/écriture et un autre pour la lecture seule. Ceci est décrit brièvement dans le lien précédent, section "puis-je utiliser deux opérations en une session", mais nécessite plus de votre mise en œuvre.
Ce n'est pas seulement "utiliser des transactions pour les lire", c'est aussi: "utilisation de la même transaction que vous utilisez pour l'écriture que pour la lecture". (et puis, c'est vrai, et l'application réelle dépendra de vos schémas actuels, combien de niveaux il y a, de la mise en cache et de la configuration).
Mise à jour: élargi un peu, supprimé certaines ambiguïtés