Использование Linq (nHibernate) для выполнения оператора Case с помощью Counts - PullRequest
0 голосов
/ 24 марта 2011

Я уверен, что это кто-то сделал дома несколько раз, но я никогда не нашел решения ...

Так что можно сделать что-то подобное, используя nHibernate 3 с предпочтительно Linq:

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

Я почти уверен, что это невозможно и что лучшее решение - в этом случае выбрать только sql ... но, может быть, в nHibernate 3.1 есть что-то новое, что можно сделать даже с использованием queryover?

спасибо

Ответы [ 2 ]

2 голосов
/ 26 марта 2011

Вы можете сделать это с HQL, который почти совпадает с 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

(я не уверен, что COUNT будет работать, я уверен, что SUM работает)

Вот версия LINQ, которая также должна работать:

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

Вы можете использовать Projections.Conditional с Criteria или QueryOver, но это больше работы.

2 голосов
/ 25 марта 2011

Вы можете получить желаемый результат с помощью QueryOver, хотя он будет медленнее из-за подзапросов.

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[]>();

Объяснение:

Я использую два отдельных QueryOvers. Первый подсчитывает строки в Tutorials, где IsWithdrawn = true, второй подсчитывает все строки. Затем два отдельных QueryOvers используются в качестве подзапросов в обычном QueryOver с проекцией (SelectList).

Вот сгенерированный SQL:

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_;
...