LinqNhibernate / OrderBy and reference

27 views
Skip to first unread message

Kakone

unread,
Jun 24, 2010, 7:59:12 AM6/24/10
to nhusers
Hello,

I have a project class with a Type property (it's a nullable reference
to a ProjectType entity).

I want to order like this :
Session.Query<Project>().OrderBy(p.Type.Label).ToList()
When I do this, I don't get the objects where Type property value is
null.

So, I tried to write this :
Session.Query<Project>().OrderBy(p => p.Type == null ? null :
p.Type.Label).ToList()
But, in this case, I've got an exception : "No persister for :
xx.xxx.EntityBase"

What can I do to get all the objects including those with Type ==
null ?


Cordially,
Kakone.

Oskar Berggren

unread,
Jun 24, 2010, 8:44:47 AM6/24/10
to nhu...@googlegroups.com
Maybe there are other solutions, but one way is to do ToList() before
OrderBy(). The ordering will then happen in your application, instead
of in SQL. You would need the code from your second try of course, to
avoid null reference exceptions.

/Oskar


2010/6/24 Kakone <stepht...@gmail.com>:

> --
> You received this message because you are subscribed to the Google Groups "nhusers" group.
> To post to this group, send email to nhu...@googlegroups.com.
> To unsubscribe from this group, send email to nhusers+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nhusers?hl=en.
>
>

Kakone

unread,
Jun 24, 2010, 9:15:51 AM6/24/10
to nhusers
I can't to do it by code because most of the time, I will use it with
the Take(x) method.

For example :
Session.Query<Project>().OrderBy(p.Type.Label).Take(10)

It's a very simple request, I wonder me if I do something wrong or
it's a bug of LinqNHibernate.

On 24 juin, 14:44, Oskar Berggren <oskar.bergg...@gmail.com> wrote:
> Maybe there are other solutions, but one way is to do ToList() before
> OrderBy(). The ordering will then happen in your application, instead
> of in SQL. You would need the code from your second try of course, to
> avoid null reference exceptions.
>
> /Oskar
>
> 2010/6/24 Kakone <stephtheb...@gmail.com>:
>
>
>
> > Hello,
>
> > I have a project class with a Type property (it's a nullable reference
> > to a ProjectType entity).
>
> > I want to order like this :
> > Session.Query<Project>().OrderBy(p.Type.Label).ToList()
> > When I do this, I don't get the objects where Type property value is
> > null.
>
> > So, I tried to write this :
> > Session.Query<Project>().OrderBy(p => p.Type == null ? null :
> > p.Type.Label).ToList()
> > But, in this case, I've got an exception : "No persister for :
> > xx.xxx.EntityBase"
>
> > What can I do to get all the objects including those with Type ==
> > null ?
>
> > Cordially,
> > Kakone.
>
> > --
> > You received this message because you are subscribed to the Google Groups "nhusers" group.
> > To post to this group, send email to nhu...@googlegroups.com.
> > To unsubscribe from this group, send email to nhusers+u...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/nhusers?hl=en.- Masquer le texte des messages précédents -
>
> - Afficher le texte des messages précédents -

Kakone

unread,
Jun 24, 2010, 9:22:27 AM6/24/10
to nhusers
I should mention that I use the latest trunk version of NHibernate
3.0.
> > > For more options, visit this group athttp://groups.google.com/group/nhusers?hl=en.-Masquer le texte des messages précédents -
>
> > - Afficher le texte des messages précédents -- Masquer le texte des messages précédents -

Diego Mijelshon

unread,
Jun 24, 2010, 9:43:19 AM6/24/10
to nhu...@googlegroups.com
Hmmm... it's slightly unexpected as a behavior, although it's consistent with the equivalent HQL:

  from Project order by Project.Type.Label

It generates an inner join (actually, a select from two tables with a where clause)

With HQL you can use explicit left joins:

select project
from Project project
left join project.Type as type
order by type.Label

But I don't know if it's possible with Linq...

   Diego


Mohamed Meligy

unread,
Jun 24, 2010, 4:05:34 PM6/24/10
to nhu...@googlegroups.com
You can do left join in the QueryOver API (very similar to LINQ method chaining) you can do something like:

session.QueryOver<Project>().Left.JoinQueryOver(p => p.Type).OrderBy(p => p.Type.Label).Take(...);

(warning: not tested, try also session.QueryOver<ProjectType>() if p.Type doesn't work. I haven't tried the code and there is no XML documentation to advise)
 

Regards,

--
Mohamed Meligy
Senior Developer (Microsoft Technologies - Technical Delivery)
Injazat Data Systems
P.O. Box: 8230 Abu Dhabi, UAE
[ Local Time Offset:  GMT +4 ]

Direct:  +971   2 4045385
Mobile: +971 50 2623624, +971 55 2017 621

E-mail: eng.m...@gmail.com
Weblog: http://gurustop.net

Diego Mijelshon

unread,
Jun 24, 2010, 4:30:22 PM6/24/10
to nhu...@googlegroups.com
It would actually be 
  session.QueryOver<Project>().Left.JoinQueryOver(p => p.Type).OrderBy(t => t.Label).Asc
The problem is, that is equivalent to:

select project
from Project project
left join fetch project.Type as type
order by type.Label

...because QueryOver is just a pretty face for Criteria, and joins in Criteria always fetch the association.
Also, it has none of the benefits of Linq, except the familiar syntax.

   Diego

Mohamed Meligy

unread,
Jun 24, 2010, 4:52:57 PM6/24/10
to nhu...@googlegroups.com
So, for join fetch the Left.JoinQueryOver(...) is equivalent to myQueryOver.Fetch( x => x.Ref).Eager ?

--
Mohamed Meligy
Senior Developer (Microsoft Technologies - Technical Delivery)
Injazat Data Systems
P.O. Box: 8230 Abu Dhabi, UAE
[ Local Time Offset:  GMT +4 ]

Direct:  +971   2 4045385
Mobile: +971 50 2623624, +971 55 2017 621

E-mail: eng.m...@gmail.com
Weblog: http://gurustop.net


Diego Mijelshon

unread,
Jun 24, 2010, 4:59:26 PM6/24/10
to nhu...@googlegroups.com
No, that just sets join fetching. Left.JoinQueryOver changes the criteria "context" to an association, like CreateCriteria.

   Diego

Oskar Berggren

unread,
Jun 24, 2010, 5:09:38 PM6/24/10
to nhu...@googlegroups.com
This compiles, but is untested. No idea if correct or supported in NH.
But based on docs this seems like a starting point.

var obj = from p in Session.Query<Project>()
join t in Session.Query<Type>() on p.Type equals
t into mygroup
from item in mygroup.DefaultIfEmpty()
orderby item.Label
select o;


http://msdn.microsoft.com/en-us/library/bb397895.aspx
http://msdn.microsoft.com/en-us/vbasic/bb737929.aspx#grpjoinleftout
http://msdn.microsoft.com/en-us/library/bb311040.aspx


/Oskar


2010/6/24 Diego Mijelshon <di...@mijelshon.com.ar>:

Diego Mijelshon

unread,
Jun 24, 2010, 5:15:06 PM6/24/10
to nhu...@googlegroups.com
That doesn't work... :-(

   Diego

Stefan Wenig

unread,
Jun 28, 2010, 5:10:55 AM6/28/10
to nhusers
While I don't know much about the specific implementation of LINQ 2
NH, I know the library beneath it (re-linq) and LINQ itself, so let me
try to help sort out what's broken and what could be done.

The behavior you report is probably unexpected. However, it's not
necessarily wrong. The semantics of the translation of LINQ to
(ultimately) SQL are largely undefined. Your query would just fail in
LINQ 2 objects, so that's not a helpful reference. You could look into
LINQ 2 SQL, which is sometimes taken as some kind of reference
implementation.

However, NH translates LINQ to HQL first, and this translation looks
absolutely reasonable. So to change the default behaviour, we would
have to either
- change the behavior of HQL to use outer joins (unlikely, because
there's probably either a good reason or at least a backwards
compatibility argument to be made)
- translate that LINQ to an explicit outer join in HQL

Two workarounds were suggested: using the ternary operator ( ? : ) or
using explicit outer joins in LINQ (via DefaultIfEmpty). Both could be
supported in LINQ 2 HQL, but I don't know whether this is planned, or
for when. See http://blogs.imeta.co.uk/sstrong/archive/2009/12/16/823.aspx

You can always offer to help out on the dev list:
http://groups.google.com/group/nhibernate-development

Cheers,
Stefan
> > > For more options, visit this group athttp://groups.google.com/group/nhusers?hl=en.-Masquer le texte des messages précédents -
>
> > - Afficher le texte des messages précédents -- Hide quoted text -
>
> - Show quoted text -

Kakone

unread,
Jun 28, 2010, 1:04:12 PM6/28/10
to nhusers
If I do this :
Session.Query<Project>().Fetch(p => p.Type);
An outer join is generated.

So, I wrote this :
Session.Query<Project>().Fetch(p => p.Type).OrderBy(p=>p.Type.Label);
But, it doesn't work :-(
I've got an exception : Specified method is not supported...
We can't do an OrderBy (or Count) after the Fetch method.

I tried this :
Session.Query<Project>().OrderBy(p=>p.Type.Label).Fetch(p => p.Type);
The outer join is not generated.

Strange... Isn't it ?
I think I will look at the source code...

On 28 juin, 11:10, Stefan Wenig <stefan.we...@rubicon.eu> wrote:
> While I don't know much about the specific implementation of LINQ 2
> NH, I know the library beneath it (re-linq) and LINQ itself, so let me
> try to help sort out what's broken and what could be done.
>
> The behavior you report is probably unexpected. However, it's not
> necessarily wrong. The semantics of the translation of LINQ to
> (ultimately) SQL are largely undefined. Your query would just fail in
> LINQ 2 objects, so that's not a helpful reference. You could look into
> LINQ 2 SQL, which is sometimes taken as some kind of reference
> implementation.
>
> However, NH translates LINQ to HQL first, and this translation looks
> absolutely reasonable. So to change the default behaviour, we would
> have to either
> - change the behavior of HQL to use outer joins (unlikely, because
> there's probably either a good reason or at least a backwards
> compatibility argument to be made)
> - translate that LINQ to an explicit outer join in HQL
>
> Two workarounds were suggested: using the ternary operator ( ? : ) or
> using explicit outer joins in LINQ (via DefaultIfEmpty). Both could be
> supported in LINQ 2 HQL, but I don't know whether this is planned, or
> for when. Seehttp://blogs.imeta.co.uk/sstrong/archive/2009/12/16/823.aspx
> > > > For more options, visit this group athttp://groups.google.com/group/nhusers?hl=en.-Masquerle texte des messages précédents -
>
> > > - Afficher le texte des messages précédents -- Hide quoted text -
>
> > - Show quoted text -- Masquer le texte des messages précédents -

Steve Strong

unread,
Jul 6, 2010, 5:55:35 AM7/6/10
to nhu...@googlegroups.com
Currently, there's no way of explicitly specifying a left join within the Linq syntax that's supported by the current (v3) provider.  The approach recommended by Oskar (below) is the standard way of doing a left join within Linq, but right now the provider will throw an UnsupportedException if you try to run it.

I'll push explicit left join support up my todo list, and also take a look at why the ternary operator approach was failing.

Cheers,

Steve
Reply all
Reply to author
Forward
0 new messages