1

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

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>();

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

更新 (2)

我尝试了 Sirrocco 的 SqlGroupProjection 建议(谢谢 Sirrocco),但结果是空的。首先它给了我一个错误,说它找不到属性 pcount,这意味着我需要删除订单,这意味着它是按某个时间戳排序的,这是行不通的。但即便如此,它仍然只输出用户被引用的次数,而不是加入用户表的用户 ID。有任何想法吗?谢谢。

4

2 回答 2

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;

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

于 2009-05-28T12:37:11.757 回答
0

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

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

2)然后执行:

GetSession().CreateCriteria(typeof(User))
    .Add(Expression.InG<int>("Id", topTenIdArray))
    .List<User>();
于 2009-03-23T11:52:49.693 回答