1

我正在使用 SQL Server 2008 上的 NHibernate 在特定实体上实现标记。我现在拥有的结构是简化的,如下所示:

public class Entity {
    public Guid Id { get; set; }
}

public class Tag {
    public Guid Id { get; set; }
    public string Name { get; set; }
}

public class TagAssoc {
    public Tag LinkedTag { get; set; }
    public Entity LinkedEntity { get; set; }
    //User
    //Other properties
}

没什么特别的:一个实体可以用同一个标签多次标记,因为该关联还包括有关标记该实体的用户和其他内容的数据。

现在,我正在尝试获取特定实体的标签列表,以及标签被应用的次数。在 HQL 中是这样的:

select tass.LinkedTag, count(tass.LinkedTag)
from TagAssoc as tass left outer join tass.LinkedTag as t
group by tass.LinkedTag

这会生成以下 SQL 查询:

select tag1_.Id as Id0_, tag1_.Name as Name0_, tag1_.Id as x0_0_, count_big(tag1_.Id) as x1_0_
from BandTags tagassoc0_ left outer join Tags tag1_ on tagassoc0_.TagId=tag1_.Id
group by tag1_.Id

这看起来是正确的,但在 SQL Server 2008 中不起作用,因为 Tag 的 Name 属性不包含在“group by”子句中。为了使其工作,我必须手动调整 group by 子句以包含 Tag 类的所有属性:

select tass.LinkedTag, count(tass.LinkedTag)
from TagAssoc as tass left outer join tass.LinkedTag as t
group by tass.LinkedTag.Id, tass.LinkedTag.Name

但这取决于 Tag 类的属性,因此每次更改类时都必须更新。还有其他方法可以使第一个 HQL 查询工作吗?也许某些 HQL 语法会自动使“分组依据”属性显式?

谢谢

4

1 回答 1

1

似乎没有任何方法可以让 NHibernate 按属性自动确定组。该文档甚至似乎在他们为聚合函数提供的示例 HQL 中暗示了这一点:

select cat, count( elements(cat.Kittens) ) from Eg.Cat cat group by cat.Id, cat.Weight, ...

他们还明确指定了 Cat 的属性。

如果您想动态构建一个每次类更改时都不需要更新的查询,我认为您会遇到反射和 Criteria 接口。

ProjectionList list = Projections.ProjectionList();
foreach (PropertyInfo prop in typeof(Tag).GetProperties())
{
    list.Add(Projections.GroupProperty(prop.Name));
}
list.Add(Projections.Property("LinkedTag"));
list.Add(Projections.Count("LinkedTag"));

session.CreateCriteria(typeof(TagAssoc)).SetProjection(list).List();

我还没有尝试过,所以它可能有效,也可能无效,或者可能需要一些调整,但你明白了。您可能会认为 Tag 类不会发生足够的变化而不值得麻烦。

于 2009-04-16T15:26:41.927 回答