2011-03-24 1 views
0

Je suis sûr que ce soit on a fait les maisons à quelques reprises, mais je ne l'ai jamais trouvé une solution ...LINQ (NHibernate) pour effectuer une déclaration de cas avec des comptes

Ainsi est-il possible de faire quelque chose comme ceci en utilisant NHibernate 3 avec de préférence Linq:

SELECT 
COUNT(CASE WHEN IsWithdrawn = 1 THEN 1 END) AS WithdrawnCount, 
COUNT(CASE WHEN IsWithdrawn = 0 THEN 1 END) AS ViewAllCount 
FROM Tutorials 

Je suis assez sûr que ce soit est pas possible et que la meilleure solution est d'opter seulement pour sql dans ce cas ... mais peut-être il y a quelque chose nouveau dans nHibernate 3.1 qui peut le faire avec, même en utilisant queryover?

grâce

Répondre

2

Vous pouvez le faire avec HQL, ce qui est presque le même que SQL:

SELECT 
SUM(CASE WHEN IsWithdrawn = 1 THEN 1 ELSE 0 END) AS WithdrawnCount, 
SUM(CASE WHEN IsWithdrawn = 0 THEN 1 ELSE 0 END) AS ViewAllCount 
FROM Tutorials 

(Je ne sais pas si le nombre fonctionnerait , je suis sûr que SUM ne)

est ici une version LINQ qui devrait fonctionner aussi:

session.Query<Tutorial>() 
     .GroupBy(x => x.IsWithdrawn) 
     .Select(x => new { x.Key, Count = x.Count() }) 

Vous pouvez utiliser Projections.Conditional avec des critères ou QueryOver, mais c'est plus de travail.

2

Vous pouvez obtenir le résultat souhaité avec QueryOver, bien qu'il sera plus lent en raison des sous-requêtes.

var sums = repo.Session.QueryOver<Tutorials>() 
    .SelectList(list => list 
     .SelectSubQuery<Tutorials>(NHibernate.Criterion.QueryOver.Of<Tutorials>() 
      .Where(t => t.IsWithdrawn) 
      .ToRowCountQuery()) 
     .SelectSubQuery<Tutorials>(NHibernate.Criterion.QueryOver.Of<Tutorials>() 
      .ToRowCountQuery()) 
    ) 
    .Take(1) // we want only one row in our result. In SQL I would use " from dummy". 
    .List<object[]>(); 

Explication:

J'utilise deux QueryOvers détachées. Le premier compte les lignes dans Tutorials où IsWithdrawn = true, la seconde compte toutes les lignes. Les deux QueryOver détachés sont ensuite utilisés comme SubQueries dans un QueryOver normal avec une Projection (SelectList).

Voici le SQL généré:

SELECT TOP (1) 
(SELECT count(*) as y0_ FROM [Tutorials] this_0_ 
WHERE this_0_.IsWithdrawn = True) as y0_, 
(SELECT count(*) as y0_ FROM [Tutorials] this_0_) as y1_ 
FROM [Tutorials] this_; 
+0

Exécution à travers un profileur sql la différence bewteen en utilisant des déclarations de cas sur les sous-requêtes est de 61% contre 39%. Malheureusement, alors que la solution ci-dessus fonctionne, il est tout simplement trop pour un coût de performance à utiliser. Si une requête ne va pas frapper trop souvent, c'est une bonne option;) – Jay