tags:

views:

1098

answers:

6

I am using NHibernate with a SQL query to populate some entity objects.

I have an Item object which references a User object (to indicate the owner of the Item)

class Item
{
public User User;
}

My SQL query is (it's actually more complicated, which is why I can't use HQL, but I started with this to make sure the AddJoin/AddEntity was working):

SELECT {i.*}, {u.*}
FROM Item i INNER JOIN User u ON (i.UserId = u.Id)
WHere i.Id = 5

Here is my code:

var x = session.CreateSQLQuery(sql)
    .AddEntity("i", typeof(Item))
    .AddJoin("u", "i.User")
    .List();

When I run this, I get a two-dimensional array. Each item in the array contains an Item object (with the User property initialized) and the User object itself.

What am I missing? I was hoping to get a list of Item objects with the User property initialized (which is how I interpreted the documentation).

A: 

What happens if you omit the AddJoin method ? Isn't it enough to just specify AddEntity ?

Frederik Gheysels
+1  A: 

It's been a while, but I think you're missing this:

.SetResultTransformer(new DistinctEntityRootTransformer())
Ben Scheirman
Thanks Ben. I added this - .SetResultTransformer(new DistinctRootEntityResultTransformer()) - but then I get a list of Users, instead of the desired list of Items. I would think the Root Entity would be Item, so something else must be wrong.
Nebakanezer
This doesn't work when there is another addjoin. You need to roll your own DistinctRootEntityResultTransformer. See below.
Trent
A: 

If your mapping is right you can just use a join fetch to get this all in a single hit like so:

var x = session.CreateQuery("from Item i join fetch i.User").List<Item>();
David M
Thank you David, but the actual SQL is much more complicated than what I included. I needed to understand why the basic SQL doesn't return what I expect since I can't use HQL for the final solution.
Nebakanezer
A: 

Do you resolve this problem?

+2  A: 

I just wasted an afternoon to figure this out. SetResultTransformer(CriteriaUtil.DistinctRootEntity) operates on the last thing added.

Here is what I did to get the first entity from the query. One catch though, I had to modify the NHibernate.DistinctRootEntityResultTransformer.TransformTuple() to be virtual. Not a big deal for us, because we have already branched NHibernate for some trivial additions like this. If you don't want to branch NH, it would be easy to roll your own IResultTransformer, making sure the items are unique.

add this to your query:

query.SetResultTransformer(new FirstTupleDistinctResultTransformer());

and this is the new class:

public class FirstTupleDistinctResultTransformer : DistinctRootEntityResultTransformer
{
    public override object TransformTuple(object[] tuple, string[] aliases)
    {
        return tuple[0];
    }
}
Trent
A: 

Pulling my hair out trying to fix this problem in Java. Hibernate sucks;) Any idea how to fix this - im having the exact same problem as Nebakanezer ...

Ricardo