0

我正在我的 NHibernate 3.3.3.4000 项目中编写一个包含分组和计数的摘要查询。我有域对象PositionTag,具有多对多的关系。一个职位会有几个标签,但随着时间的推移,每个标签都会有大量职位。所以这种关系是单向的,其中 Position 有一组标签,但反之则不然。

我的查询将计算每个标签的位置数,用于连接到某个特定的位置AcademicTerm(位置中的标量引用)。下面的查询有效:

    public IPartialResult<TagSummary> GetTagSummaries(string termCode, int skip, int take)
    {
        Tag tagAlias = null;
        AcademicTerm termAlias = null;
        TagSummary summary = null;

        var tagQuery = Session.QueryOver<Position>()
            .JoinAlias(p => p.Term, () => termAlias)
            .Where(() => termAlias.TermCode == termCode)
            .JoinQueryOver<Tag>(t => t.Tags, () => tagAlias)
            .SelectList(projections => projections
                .SelectGroup(p => tagAlias).WithAlias(() => summary.Tag)
                .SelectCount(p => p.ID).WithAlias(() => summary.PositionCount))     
            .TransformUsing(Transformers.AliasToBean<TagSummary>());

        var countQuery = tagQuery.ToRowCountQuery().FutureValue<int>();

        var resultQuery = tagQuery
            .OrderBy(t => t.Name).Asc
            .Skip(skip)
            .Take(take)
            .Future<TagSummary>();

        return new PartialResult<TagSummary>(resultQuery, countQuery.Value);

结果类型为TagSummary

public class TagSummary
{
    public string TagName { get; set; }
    public int PositionCount { get; set; }
}

里面有 Tag 的 Name 属性,但我真正想要的是 Tag 本身。我不知道该怎么做。我在那里有tagAlias权利,但我不知道如何将它放入我的 TagSummary。我是否必须选择每个单独的属性Tag?我可以选择标签的 ID 值,然后执行另一个查询,但这似乎不太好。

更新 我刚刚发现计数查询不起作用,因为ToRowCountQuery会去掉分组。现在我正试图解决那个问题。

4

1 回答 1

0

为了回答我自己的问题,我最终创建了一个Tagcalled的子类SummarizedTag,它添加了一个 count 属性。然后我更改了查询以选择 的所有单个属性Tag,并计算计数,然后将它们水合为SummarizedTags。因为它们是 的子类Tag,所以在视图中处理它们会更简洁一些。如果要向其中添加更多属性,我将不得不更新查询Tag;这似乎是不可避免的。

要使用分组查询处理分页,我必须“手动”构建第二个查询,而不是ToRowCountQuery()在第一个查询上使用。

public IPartialResult<SummarizedTag> GetSummarizedTags(string termCode, int skip, int take)
    {
        Logger.DebugFormat("GetSummarizedTags: termCode={0}, skip={1}, take={2}", termCode, skip, take);

        Tag tagAlias = null;
        AcademicTerm termAlias = null;
        SummarizedTag summary = null;

        // Get all tags attached to positions in specified term, with their use counts
        var tagQuery = Session.QueryOver<Position>()
            .Where(p => p.Status == PositionStatus.Published)
            .JoinAlias(p => p.Term, () => termAlias)
            .Where(() => termAlias.TermCode == termCode)
            .JoinQueryOver<Tag>(t => t.Tags, () => tagAlias)
            .SelectList(projections => projections
                .SelectGroup(() => tagAlias.ID).WithAlias(() => summary.ID)
                .SelectGroup(() => tagAlias.Name).WithAlias(() => summary.Name)
                .SelectGroup(() => tagAlias.Active).WithAlias(() => summary.Active)
                .SelectGroup(() => tagAlias.Description).WithAlias(() => summary.Description)
                .SelectGroup(() => tagAlias.UrlFormatName).WithAlias(() => summary.UrlFormatName)
                .SelectCountDistinct(p => p.ID).WithAlias(() => summary.Count))
            .TransformUsing(Transformers.AliasToBean<SummarizedTag>())
            .OrderByAlias(() => summary.Count).Desc
            .Skip(skip)
            .Take(take)
            .Future<SummarizedTag>();

        // Count tags used in positions in specified term.
        var countQuery = Session.QueryOver<Position>()
            .JoinAlias(p => p.Term, () => termAlias)
            .Where(() => termAlias.TermCode == termCode)
            .JoinQueryOver<Tag>(p => p.Tags, () => tagAlias)
            .Select(Projections.CountDistinct(() => tagAlias.ID))
            .FutureValue<int>();

        return new PartialResult<SummarizedTag>(tagQuery, countQuery.Value);
    }
于 2013-09-18T18:32:27.113 回答