Opérations NHibernate sur les lectures

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? 😉

Ce message de l’un des auteurs pourrait avoir votre réponse:

Même si nous ne lisons que des données, nous souhaitons utiliser une transaction, car l’utilisation d’une transaction garantit l’obtention d’un résultat cohérent à partir de la firebase database. NHibernate présume que tout access à la firebase database est effectué dans le cadre d’une transaction et décourage fortement toute utilisation de la session sans transaction.

Laissant de côté le problème de la sécurité lié au traitement des transactions, l’hypothèse selon laquelle les transactions sont coûteuses et que nous devons les optimiser est fausse. Comme déjà mentionné, les bases de données fonctionnent toujours en transaction. Et les bases de données ont été fortement optimisées pour fonctionner avec des transactions. La question est de savoir quoi que ce soit par déclaration ou par lot. Il y a un peu de travail à faire pour créer et aliéner une transaction, et le faire par déclaration est en réalité plus coûteux que de le faire par lot.

Ce que les autres ont dit est vrai, mais ils n’ont pas précisé que le problème de ne pas contrôler vous-même les transactions est que si vous effectuez plusieurs opérations NHibernate sans transaction explicite, chacune de ces opérations aura lieu dans des transactions séparées .

Ainsi, vous pouvez facilement obtenir des incohérences entre les opérations. En démarrant explicitement une transaction NHibernate puis en effectuant les opérations correspondantes, vous êtes assuré de la cohérence de ces opérations.

Ceci est bien sûr vrai pour TOUT couche d’access aux données qui, implicitement, lance des transactions pour vous si ce n’est pas le cas. Ce 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’access à la firebase database 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 tu n’utilises pas de transactions. Il est habituel, mais non obligatoire, de fermer la session à la fin du traitement, mais avant de commencer à lire les données (c.-à-d. La vue). Cette méthode est propagée sous le terme ” Open Session in View ” (bien qu’elle ait évidemment un motif pour empêcher la lecture avant la fermeture). Ce modèle est souvent utilisé dans les applications Web où la session est ouverte à l’arrivée de la demande et fermée juste avant l’écriture dans le stream de réponses.

(N) Hibernate a besoin d’une session et d’une transaction. Lorsque vous lisez sans utiliser de transaction explicite, la transaction sera configurée pour vous. Lorsque vous lisez après qu’une transaction est validée, le comportement dépend de la configuration et du pilote de NH.

ODBC et JDBC ne définissent pas ce qui se passe lorsqu’une connexion est fermée et qu’il existe des données non validées ou non restaurées. Lorsque la connexion est rouverte, il est possible qu’une nouvelle transaction soit automatiquement lancée.

L’utilisation d’un access non transactionnel ne peut être utilisée qu’avec la définition de auto-commit explicitement dans la configuration de NHibernate. Si ce n’est pas le cas, le pilote par défaut est utilisé et il peut fonctionner ou ne pas fonctionner.

En bref, il existe de nombreuses lacunes et comportements indéfinis lorsque vous n’utilisez pas de transactions sur des lectures. Cela fonctionnera souvent, mais cela dépend de la configuration, des modèles appliqués, des pilotes. Il y a de grandes chances que vous obteniez LazyInitializationException s, résultat commun de lecture après validation sans ouverture d’une nouvelle transaction.

La “meilleure pratique” consiste à utiliser une transaction en lecture / écriture et une autre en lecture seule. Ceci est décrit brièvement dans le lien précédent, section “Puis-je utiliser deux transactions dans une session” mais nécessite plus de votre implémentation.

Ce n’est pas seulement “utiliser des transactions pour lire”, c’est aussi: “utiliser la même transaction que vous utilisez pour écrire pour lire”. (et alors, bien que cela soit vrai, l’application réelle dépendra de vos modèles actuels, du nombre de niveaux, de la mise en cache et de la configuration).

Mise à jour: élargi un peu, enlevé quelques ambiguïtés

également:
Renoncer à l’utilisation de transactions explicites a pour effet d’annuler le cache de second niveau.