4

Given the following tables:

Resources:
ID int,
Name varchar(100),
Address varchar(500),
City varchar(100),
etc.

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

every time a resource is looked at, an entry is added to the ResourceView table for that user.

Here are the corresponding classes:

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; }
}

Using NHibernate, how can I get the top 5 most viewed resources in order by the count similar to what the following sql retrieves:

select * from [resource]
where ID in (
select top 5 resourceId from resourceViews
where userId = 3
group by (resourceId)
order by count(*) desc
)

Bonus points if it can be done with Criteria API instead of hql.

3 Answers 3

5

Try this:

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

The generated SQL looks exactly like the one you have on your question. Hence I believe it is what you are looking for.

Sign up to request clarification or add additional context in comments.

1 Comment

This was almost perfect, thank you!! Points awarded and I put the final solution as a new answer for anyone else coming across this question.
2

tolism7 had it 99% of the way there, here's the final solution for anyone else with a similar problem.

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

Comments

2

DetachedCriteria is one way to do that, another way which I think is more elegant is to use LINQ.

To help someone who tried to find answer to the question in Nhibernate 3.1+ through this post like me, I will post my answer to the question here.

I am using NHibernate3.2 in which full LINQ support is available.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.