Group By使用NHibernate进行分组

时间:2010-02-22 03:22:36

标签: nhibernate

鉴于以下表格:

资源:
ID int,
名称varchar(100),
地址varchar(500),
城市varchar(100),

ResourceViews:
Id int,
resourceId int,
userId int,
viewDate DateTime

每次查看资源时,都会为该用户的ResourceView表添加一个条目。

以下是相应的类:

public class Resource
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public IList<ResourceView> ResourceViews { get; set; } // simplified
    etc. -- class simplified for question
}
public class ResourceView {
    public int Id { get; set; }
    public Resource Resource { get; set; }
    public User User { get; set; }
    public DateTime ViewDate { get; set; }
}

使用NHibernate,如何通过类似于以下sql检索的计数顺序获得前5个查看次数最多的资源:

从[资源]中选择* 其中ID为(
  从resourceViews中选择前5个resourceId   userId = 3的地方   group by(resourceId)
  按次数排序(*)desc

如果可以使用Criteria API而不是hql来完成加分。

3 个答案:

答案 0 :(得分:5)

试试这个:

DetachedCriteria dcriteria = DetachedCriteria.For<ResourceView>("rv")
                        .Add(Restrictions.Eq("userId", 3))
                        .SetProjection(Projections.GroupProperty("rv.PostID"))
                        .AddOrder(Order.Desc(Projections.Count("rv.Id")))
                        .SetMaxResults(5);

var results = NHibernateSessionManager.Session.CreateCriteria<Resource>("r")
                            .Add(Subqueries.PropertyIn("r.Id", dcriteria))
                            .List<Resource>();

生成的SQL看起来与您在问题上的SQL完全一样。因此,我相信这正是你要找的。

答案 1 :(得分:2)

tolism7有99%的路程,这里是其他遇到类似问题的最终解决方案。

var dcriteria = DetachedCriteria.For<ResourceView>("rv")
                .Add(Restrictions.Eq("User", user))
                .SetProjection(Projections.GroupProperty("rv.Resource"))
                .AddOrder(Order.Desc(Projections.Count("rv.Id")))
                .SetMaxResults(maxResults);
var results = Session.CreateCriteria<Resource>("r")
                .Add(Subqueries.PropertyIn("r.Id", dcriteria))
                .List<Resource>();

答案 2 :(得分:2)

DetachedCriteria是一种方法,我认为更优雅的另一种方法是使用LINQ。

为了帮助那些试图通过像我这样的帖子在Nhibernate 3.1+中找到问题答案的人,我会在这里发布我对这个问题的回答。

我正在使用NHibernate3.2,其中提供完整的LINQ支持。

using NHibernate.Linq;

        var session = Application.SessionFactory.GetCurrentSession();

        var _query = from r in session.Query<Resource>()
                     orderby r.ResourceViews.Count
                     select r;
        return _query.Take(maxResults).ToList();