web-dev-qa-db-fra.com

Quelle est la différence entre NHibernate Query <> et QueryOver <>?

Je viens de commencer avec NHibernate (en utilisant SQLite) dans mon projet actuel et j'ai surtout utilisé Query<>, car je connaissais bien l'écriture de requêtes db dans Linq.

Lorsque j'ai été confronté à des requêtes plus complexes, j'ai fait des recherches sur QueryOver<> et a pensé qu'il devrait être préféré à Query<> car "La syntaxe QueryOver est spécifique à NH". De plus, il ne semble y avoir rien qui Query<> peut faire ça QueryOver<> ne peut pas accomplir.

J'ai donc commencé à remplacer toutes les utilisations de Query<> en conséquence. Il ne fallut pas longtemps avant que j'eus le premier "problème" où l'utilisation de Query<> semblait juste plus pratique. Exemple (sélectionnez la valeur la plus élevée dans la colonne CustomNumber dans le tableau BillingDataEntity):

int result = Session.Query<BillingDataEntity>().Select(x => x.CustomNumber).OrderByDescending(a => a).FirstOrDefault();
int result = Session.QueryOver<BillingDataEntity>().Select(x => x.CustomNumber).OrderBy(a => a.CustomNumber).Desc.Take(1).SingleOrDefault<int>();

Ce que je n'aime pas, c'est la nécessité de convertir explicitement le résultat en int et que la version Query <> est simplement plus facile à lire. Suis-je en train de me tromper complètement, ou en d'autres termes: existe-t-il une meilleure façon de le faire?

J'ai jeté un œil à la sortie SQL générée:

NHibernate: select billingdat0_.CustomNumber as col_0_0_ from "BillingDataEntity" billingdat0_ order by billingdat0_.CustomNumber desc limit 1
NHibernate: SELECT this_.CustomNumber as y0_ FROM "BillingDataEntity" this_ ORDER BY this_.CustomNumber desc limit @p0;@p0 = 1 [Type: Int32 (0)]

Qu'est-ce que je regarde exactement? S'agit-il de la requête "interne" (dépendante de la méthode) que NHibernate traduit en outre dans la requête de base de données réelle?

28
Rev1.0

Il y a beaucoup de réponses concernant QueryOver contre Query ici sur Stackoverflow mais en un mot: -

QueryOver est une version fortement typée de Criteria et est plus spécifique à NHibernate. Presque tout ce que vous pouvez faire dans ICriteria peut être fait avec QueryOver. À l'époque dorée de ICriteria NH2, vous deviez toujours lancer, c'est pourquoi vous devez maintenant lancer à la fin de la chaîne de retour à un int.

LINQ (Query) est une méthode de requête standard qui fonctionne sur IQueryable qui n'a pas besoin de références explicites à NHibernate et peut être considérée comme plus agnostique ORM et suit donc la norme linq. Comme vous l'avez souligné à juste titre, vous n'avez pas besoin de transtyper en entier car vous sélectionnez dans le résultat le numéro personnalisé.

Je serais très surpris de votre exemple simple si le SQL généré était très différent.

J'étais un grand fan de QueryOver mais comme le fournisseur Linq devient plus mature que 95% de mes requêtes, j'utilise Query mais pour certains trucs spécifiques à Nhibernate, j'ai recours à QueryOver. Quoi qu'il en soit, je recommande d'utiliser un outil de profilage pour voir avec quoi vous pouvez vivre.

Réfs: compromis ou versus et versus

34
Rippo

À propos de votre version de QueryOver, j'aurais écrit:

int result = Session.QueryOver<BillingDataEntity>()
               .Select(Projections.Max<BillingDataEntity>(x => x.CustomNumber))
               .SingleOrDefault<int>();

Cela semble assez lisible, et le SQL résultant serait quelque chose comme:

SELECT max(this_.CustomNumber) as y0_ FROM "BillingDataEntity" this_

J'espère que cela vous aidera

2
jbl