У меня проблема с NHibernate, что, похоже, я не могу найти простой способ.
У меня есть следующая база данных:
Игра: ID, счет, Match_ID
Совпадение: идентификатор
Совпадение состоит из 3 игр.
Я хочу узнать, что такое максимальная оценка матча, поэтому следующий SQL-код выполнит трюк:
select max(a.total) from
(select Match.ID, sum(Game.Score) as total
from Game inner join Match
on Game.Match_ID = Match.ID
group by Match.ID) a
В NHibernate это выглядит немного сложнее. По-видимому, HQL не разрешает подзапросы в предложении from, поэтому я не могу это использовать.
Я уверен, что это можно сделать с ICriteria, но я только начал использовать NH, поэтому я не могу понять, как это понять. Я в основном понял следующее:
Session.CreateCriteria<Game>()
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("Match"))
.Add(Projections.Sum("Score"))).List();
После этого я играл с различными наборами DetachedCriteria, но, похоже, кругом крутился.
Для мира HQL один запрос выполняет трюк...
var maxScore = session.CreateQuery(@"select sum(game.Score)
from Game game
group by game.Match
order by sum(game.Score) desc")
.SetMaxResults(1)
.UniqueResult<long>();
Надеюсь, что это поможет.
Обновление: И для мира критериев может быть лучшее преобразование результата, но это только работает:)
var max = (int)session.CreateCriteria<Game>("game")
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("game.Match"))
.Add(Projections.Sum("game.Score"), "total"))
.AddOrder(Order.Desc("total"))
.SetMaxResults(1)
.SetResultTransformer(Transformers.AliasToEntityMap)
.UniqueResult<IDictionary>()["total"];
Я бы сделал это так в SQL:
select top 1 Match.ID, sum(Game.Score) as total
from Game inner join Match
on Game.Match_ID = Match.ID
group by Match.ID order by total desc
группа всегда сложна в критериях /HQL: поскольку предложение group by может возвращать только сгруппированный столбец и агрегаты любого другого столбца. Поэтому невозможно вернуть целую сущность из предложения group by, только идентификатор, который вы группируете и объединяете.
По этой причине я обычно делаю группу по запросам с использованием собственного SQL следующим образом:
ISQLQuery sqlQuery1 = NHibernateSessionManager.Instance.GetSession().CreateSQLQuery("select Match.ID, sum(Game.Score) as total from Game inner join Match on Game.Match_ID = Match.ID group by match.ID order by total desc");
sqlQuery1.AddScalar("id", NHibernateUtil.Int32); //
sqlQuery1.AddScalar("total", NHibernateUtil.Int32);
sqlQuery1.SetMaxResults(1);
var result = sqlQuery1.List();