这可能会被问过几次,我确实找到了一些同一主题的问题(一两个)。然而,这些问题相当陈旧,以及它们仍然没有答案的事实。
基本上我有一个QueryOver(尝试使用Linq到NHibernate获得相同的结果,但对Linq来说显然有点复杂):
PrintJobType printJobType = null;
var test = unitOfWork.Session.QueryOver<PrintJob>()
.JoinAlias(pj => pj.PrintJobType, () => printJobType)
.Where(pj => pj.PrintedOn == null)
.Select(Projections.ProjectionList()
.Add(Projections.Group(() => printJobType.PriorityWeight))
.Add(Projections.Group(() => printJobType.ID)))
.OrderBy(pj => printJobType.PriorityWeight).Desc
.OrderBy(Projections.Min<PrintJob>(pj => pj.ID)).Asc
.List<object[]>()
.Select(x => x[1])
.Cast<int>();
最大的问题是,对于我的生活,我无法从选择中获得分组,我只想要返回printjob类型的ID,但我似乎无法让它工作。此查询基本上由PrintJobWeight排序,然后是Min Printjob ID秒。
(所以当前查询如下:)
SELECT
printjobty1_.PriorityWeight as y0_, printjobty1_.ID as y1_
FROM
[PrintJob] this_
inner join [PrintJobType] printjobty1_ on this_.PrintJobType_id=printjobty1_.ID
WHERE
this_.PrintedOn is null
GROUP BY
printjobty1_.PriorityWeight,
printjobty1_.ID
ORDER BY
printjobty1_.PriorityWeight desc,
min(this_.ID) asc
所以我基本上只想返回printjobtype的ID。
作为'奖励',我们真正想要的是选择整个PrintJobType,因为它目前的状态我必须在选择列表之后立即进行.Load(id)调用,这对我来说似乎也是多余但我可以和我一起生活,但目前的结果对我来说似乎效率极低。
在一个完美的世界中,对服务器的查询看起来像:
SELECT
printjobty1_.*
FROM
[PrintJob] this_
inner join [PrintJobType] printjobty1_ on this_.PrintJobType_id=printjobty1_.ID
WHERE
this_.PrintedOn is null
GROUP BY
printjobty1_.*
ORDER BY
printjobty1_.PriorityWeight desc,
min(this_.ID) asc
(是的,你不能在group by子句中放置printjobty1 _。*,但它会更快,然后手工写下所有的属性和事物)
NHibernate版本:3.3.1.4000 - SQL Server 2012
答案 0 :(得分:0)
使用NHibernate的所需解决方案将使用子查询。这样我们就可以首先获得我们需要的ID (分组,排序,过滤),然后使用该ID获得清晰的结果。请在此处观察NHibernate和子查询的强大功能:
我不是100%确定你想要得到什么,但是有一个解决方案草案:
PrintJob printJob = null;
PrintJobType printJobType = null;
// simply this is the place, where we do all the magic
// to select the PrintJob.ID
// I guess that my adjustments would result in the same stuff
// as in the query above without the grouping
// ... but if not, we still do have a draft of HOW TO
var subQuery = QueryOver.Of<PrintJob>()
.JoinAlias(pj => pj.PrintJobType, () => printJobType)
.Where(pj => pj.MiddleName == null)
.SelectList(l => l
.Select(pj => pj.ID)
)
.OrderBy(() => printJobType.PriorityWeight).Desc
.OrderBy(pj => pj.ID).Asc
.Take(1)
;
// here we SELECT the clean, root object and its reference...
// that all will be executed as only ONE Select statement
var result = session.QueryOver<PrintJob>(() => printJob)
.WithSubquery
.WhereProperty(() => printJob.ID)
.In(subQuery)
.JoinAlias(x => x.PrintJobType, () => printJobType)
.SingleOrDefault<PrintJob>();
现在,出于某些测试目的,我们可以继续:
// here we say session clear just for the TEST purposes below
session.Clear();
// now, session is closed, no lazy loading, but due to JOIN ALIAS
// the PrintJobType is loaded as well
Assert.IsTrue(result != null);
Assert.IsTrue(result.PrintJobType != null);
Assert.IsTrue(result.PrintJobType.PriorityWeight != null);