views:

594

answers:

2

The problem here consists of translating a statement written in LINQ to SQL syntax into the equivalent for NHibernate. The LINQ to SQL code looks like so:

var whatevervar = from threads in context.THREADs
                          join threadposts in context.THREADPOSTs
                            on threads.thread_id equals threadposts.thread_id
                          join posts1 in context.POSTs
                            on threadposts.post_id equals posts1.post_id
                          join users in context.USERs
                            on posts1.user_id equals users.user_id
                          orderby posts1.post_time
                          where threads.thread_id == int.Parse(id)
                          select new
                          {
                              threads.thread_topic,
                              posts1.post_time,
                              users.user_display_name,
                              users.user_signature,
                              users.user_avatar,
                              posts1.post_body,
                              posts1.post_topic
                          };

It's essentially trying to grab a list of posts within a given forum thread. The best I've been able to come up with (with the help of the helpful users of this site) for NHibernate is:

var whatevervar = session.CreateQuery("select t.Thread_topic, p.Post_time, " +
                                              "u.User_display_name, u.User_signature, " +
                                              "u.User_avatar, p.Post_body, p.Post_topic " +
                                              "from THREADPOST tp " +
                                              "inner join tp.Thread_ as t " +
                                              "inner join tp.Post_ as p " +
                                              "inner join p.User_ as u " +
                                              "where tp.Thread_ = :what")
                                              .SetParameter<THREAD>("what", threadid)
                                              .SetResultTransformer(Transformers.AliasToBean(typeof(MyDTO)))
                                              .List<MyDTO>();

But that doesn't parse well, complaining that the aliases for the joined tables are null references. MyDTO is a custom type for the output:

public class MyDTO
{
    public string thread_topic { get; set; }
    public DateTime post_time { get; set; }
    public string user_display_name { get; set; }
    public string user_signature { get; set; }
    public string user_avatar { get; set; }
    public string post_topic { get; set; }
    public string post_body { get; set; }
}

I'm out of ideas, and while doing this by direct SQL query is possible, I'd like to do it properly, without defeating the purpose of using an ORM.

Thanks in advance!

EDIT:

The database looks like this: http://i41.tinypic.com/5agciu.jpg (Can't post images yet.)

A: 

When I want a HQL query to return a custom type, like you do, I always do it like this:

select new MyDTO (t.Thread_Topic, p.Post_time, u.User_Display_Name, .... ) 
from ...

I would have to check some code of mine, but I think that I don't even use the AliasToBeenTransformer in such cases. I don't know by heart, since I mostly use NHibernate's ICriteria API (and when using this one, you indeed need to specify the resulttransformer when executing such kind of operation).

NB: I find it weird (or rather awkward) to see underscores in property-names ...

Frederik Gheysels
The weird names are a result of the XML generated by NConstruct Lite, which I used to make the ORM files and whatnot. Primary keys got changed from "smth_id" to "Id" and foreign keys got changed from "smth_id" to "Smth_".
Abu Dhabi
A: 

HQL is a query on your objects, not your tables!

In your HQL I see a join between the class tp and a property of that class, tp.Thread_. You should distinguish between SQL and HQL there. Think of HQL as a query on the object TP instead of on the underlying table structure. Can you post your domain model (the relations between your objects) so that we can help you out?

Thanks for that picture. However: it looks like your objects are a copy of your tables and I do not think that is what you had in mind? For example: I would have thought that the many-to-many relation between threads and posts would have been mapped using Hibernate. If that would be the case, you could join threads with posts without having to bother with the intermediate object threadpost, which, in fact, is just holding the relationship between those objects, right?

In other words; decorate your thread object with a list of posts, and decorate the post object with a list of threads.

[decorate] That is to put a list of threads as a property on your post class, and put a list of posts as a property on your threads class. What you are looking for is the many-to-many relationship for nhibernate mapping files. That means you do not need to map the many-to-many table in a class, only map the relationship of the post and thread classes.

Hace
Yes, I'll edit it in promptly.
Abu Dhabi
I wasn't aware than NHibernate's HQL manages to do these kinds of relationships without the intermediate table - I know I couldn't do this in regular SQL without pointing out that THREADPOST holds the association between THREAD and POST.I don't know what you mean by "decorate". Could you expound?
Abu Dhabi
what he means by decorate is to add more to your entity classes besides the direct table properties. so a user has multiple posts, so add an IList<Post> to your user class, etc.
Chris Conway