Получить теги и количество тегов с помощью HQL на SQL Server 2008 - PullRequest
1 голос
/ 11 апреля 2009

Я реализую тегирование для конкретной сущности, используя NHibernate в SQL Server 2008. У меня сейчас есть упрощенная структура:

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, потому что свойство 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, который автоматически делает свойства «group by» явными?

Спасибо

1 Ответ

1 голос
/ 16 апреля 2009

Не похоже, что есть способ заставить NHibernate автоматически определять группу по свойствам. Документация даже, кажется, подразумевает это в примере HQL, который они дают для агрегатной функции:

выбор кота, количество (элементы (кот. Котята)) от группы кошек Eg.Cat по cat.Id, cat.Weight, ...

Там они также явно указывают свойства Cat.

Если вы хотите динамически создавать запрос, который не требует обновления при каждом изменении класса, я думаю, что вы застряли с Reflection и интерфейсом 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 не изменится настолько, чтобы стоить того.

...