NHibernate - selecting data from referenced objects (traversing many-to-one relationship) in a query

StackOverflow https://stackoverflow.com/questions/22231970

  •  10-06-2023
  •  | 
  •  

Question

i want to build a query that will select some columns from a joined table (many to one relationship in my data model).

var q = ses.QueryOver<Task>().Select(x => x.Id, x => x.CreatedDate, x => x.AssigneeGroup.Name, x => x.AssigneeGroup.IsProcessGroup);

Here i'm retrieving properties from AssigneeGroup which is a reference to another table, specified in my mapping. But when I try to run this query I get

Exception: could not resolve property: AssigneeGroup.Name of: Task

So it looks like NHibernate is not able to follow relations defined in my mapping and doesn't know that in order to resolve AssigneeGroup.Name we should do a join from 'Task' to 'Groups' table and retrieve Group.Name column. So, my question is, how to build such queries? I have this expression: x => x.AssigneeGroup.Name, how to convert it to proper Criteria, Projections and Aliases? Or is there a way to do this automatically? It should be possible because NHibernate has all the information...

Was it helpful?

Solution

Your query need association and should look like this:

// firstly we need to get an alias for "AssigneeGroup", to be used later
AssigneeGroup assigneeGroup = null;

var q = ses
    .QueryOver<Task>()
    // now we will join the alias
    .JoinAlias(x => x.AssigneeGroup, () => assigneeGroup) 
    .Select(x => x.Id
          , x => x.CreatedDate

          // instead of these
          // , x => x.AssigneeGroup.Name
          // , x => x.AssigneeGroup.IsProcessGroup

          // use alias for SELECT/projection (i.e. ignore "x", use assigneeGroup)
          , x => assigneeGroup.Name
          , x => assigneeGroup.IsProcessGroup
     );

More and interesting reading:

OTHER TIPS

You have to join the two tables if you wish to select columns from something other than the root table/entity (Task in our case).

Here is an example:

IQueryOver<Cat,Kitten> catQuery =
    session.QueryOver<Cat>()
        .JoinQueryOver<Kitten>(c => c.Kittens)
            .Where(k => k.Name == "Tiddles");

or

Cat catAlias = null;
Kitten kittenAlias = null;

IQueryOver<Cat,Cat> catQuery =
    session.QueryOver<Cat>(() => catAlias)
        .JoinAlias(() => catAlias.Kittens, () => kittenAlias)
        .Where(() => catAlias.Age > 5)
        .And(() => kittenAlias.Name == "Tiddles");

Alternatively you could use the nhibernate linq provider (nh > 3.0):

var q = ses.Query<Task>()
           .Select(x => new 
           { 
               Id = x.Id, 
               CreatedDate = x.CreatedDate, 
               Name = x.AssigneeGroup.Name, 
               IsProcessGroup = x.AssigneeGroup.IsProcessGroup
           });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top