如何在nhibernate中查询最常用的多对一

时间:2009-03-20 13:07:19

标签: nhibernate icriteria

我正在处理的项目中存在以下问题。系统中的每个事务都分配给给定用户。因此,事务和用户之间存在多对一关系,如下所示:

public class User 
{
    public int ID { get; private set; } 
    public string FirstName { get; set; }
    ....
}

public class Transaction 
{
    public int ID { get; private set; }
    public User CreatedBy { get; private set; } 
    ...
}

我已经使用NHibernate映射了这些实体,因此Transaction和User类之间存在多对一的映射。 User对象没有事务列表,但Transaction具有对创建它的用户的引用。

现在我想查询以检索创建了大多数事务的用户列表,但我无法弄清楚如何使用NHibernate获得前10个最多引用的用户。

有什么想法吗?我希望能够使用ICriteria来完成此操作而不是HQL,但如果需要,HQL就可以了。

更新

我尝试了sirrocco的查询建议......

DetachedCriteria topReferencedUsers = DetatchedCriteria.For(typeof(Transaction)) 
    .SetProjection(Projections.GroupProperty("CreatedBy.Id"))
    .SetProjection(Projections.Count("CreatedBy.Id").As("pcount" ))
    .AddOrder(Order.Desc("pcount"))
    .SetMaxResults(10);

并将其构建为子查询...

GetSession().CreateCriteria(typeof (User))
    .Add(Subqueries.PropertyIn("Id", topReferencedUsers))
    .List<User>();

但是此子查询不进行分组,但返回事务总数,然后将其用作User查询的IN子句。如果我用两个投影添加ProjectionList(),我得到了我想要的子查询的输出,但它失败了,因为它试图将两列输出运行到User查询的IN子句中。如何让NHibernate同时投影ID和Count,但只加入ID?

更新(2)

我尝试了Sirrocco的SqlGroupProjection建议(谢谢Sirrocco),但是空了。首先,它给了我错误,说它无法找到属性pcount,这意味着我需要删除顺序,这意味着它是按一些时间戳排序,这将无法正常工作。但即使如此,它仍然只输出用户被引用的次数,而不是用于加入Users表的用户ID。有任何想法吗?感谢。

2 个答案:

答案 0 :(得分:1)

你可以自己尝试一下,看看你是否得到了想要的输出。

var userIds = this.Session
    .CreateQuery(@"
select a.User.Id 
from Transaction as a 
group by a.User 
order by count(a.User) desc")
    .SetMaxResults(10)
    .List<int>().ToArray();

var users = this.Session.CreateCriteria(typeof(User))
    .Add(Restrictions.InG("Id", userIds))
    .List<Artist>();

return users;

我从第一次查询获得的userId是(90,22,50,55)但是当传递给第二个查询时,我以22,50,55,90的顺序获取用户。

答案 1 :(得分:0)

您可以将操作分为两个步骤。

1)执行topReferencedUsers,然后将CreatedBy.Id投影提取到内存中的int数组中(因为你只处理10)。

2)然后执行:

GetSession().CreateCriteria(typeof(User))
    .Add(Expression.InG<int>("Id", topTenIdArray))
    .List<User>();