开发者

Join tables with nested select count and group by in Nhibernate HQL

I have post, vote and comment table. Each post can have N votes and N comments. I have been trying to find a way to do this query using Nhibernate HQL with no success.

 SELECT P.Id, P.Title, P.TextDescription, ISNULL(V.TotalVotes,0), ISNULL(C.TotalComments, 0)
 FROM
 Post P

 LEFT JOIN
   (SELECT 
    PostId, count(PostId) as TotalVotes 
    FROM Vote 
    GROUP BY PostId) V
 ON V.PostId = P.Id 

 LEFT JOIN 
    (SELECT 
     PostId, count(PostId) as TotalComments
     FROM Comment 
     GROUP BY PostId) C
 ON C.PostId = P.id 

I pushed GROUP BY aggregations into nested SELECT statements because i want to group only PostId and not all those other columns. My Domain classes:

Post - properties:

int Id  { get; set; }
string Title { get; set; }
string TextDescription { get; set; }
IList<Comment> Comments { get; set; } -> HasMany
IList<Vote> Votes { ge开发者_JAVA技巧t; set; } -> HasMany

Comment - properties:

int Id  { get; set; }
Post Post { get; set; } -> reference

Vote

int Id  { get; set; }
Post Post { get; set; } -> reference

I'm really puzzled about this. I hope i'm not going in the wrong direction. Maybe i should just use the Nhibernate formula attribute in which i can declare an arbitrary SQL expression for my count's.

Any help would be very much appreciated..

Thanks!


For what you are trying to do, you do need to write any HQL query Since you have collections in your classes and you have mapped them in your .hbm.xml files like (if you are using fluent nhibernate ignore this)

<bag name="Comments" inverse="true" lazy="extra">
    <key column="CommentId" />
    <one-to-many class="Comment,mylib" />
</bag>

<bag name="Votes" inverse="true" lazy="extra">
    <key column="VoteId" />
    <one-to-many class="Vote,mylib" />
</bag>

when you call

Post post = ISession.Get<Post>(postId);

the Comments and Votes collections are initialized with a proxy. When you touch the collection as such

post.Comments.Count

NHibernate will fire a select count(*) on the Comments with a PostId of postId.

If you absolutely want to implement this with a formula (because you want the see the count each and everytime you fetch a Post) again you will not need an HQL (or Criteria for that matter) query

EDIT: Since you do not want formulas and you want to fetch the result in a single round trip, here is a solution in HQL, (the above collection mapping is required)

IQuery query = nhSession.CreateQuery("select p, count(p.Comments), p.(p.Votes) from Post p where p.id = :postId");
query.SetInt32("postId", postId);
object result = query.UniqueResult();

where result is an array (i think ArrayList) where result[0] is a Post type object, result[1] is the comment count (int/long) and result[2] is the vote count (int/long)


If you map your collections with lazy="extra", their Count property will not cause a load of the collection.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜