Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,026 | Comments: 44,842

filter by tags archive

NHibernate – query only properties

time to read 4 min | 727 words

With most applications, there is some difference between the domain model and the data model. Probably the most common scenario that I run into can be expressed in the usually Blog & Posts example. In our domain model, we don’t want to have a Blog.Posts collection, we want to only have a Post.Blog.

However, in the data model, all associations are bidirectional, but that doesn’t mean that we want to have the same in the domain model. The problem is that we still want to query on that. That is a bummer, right? Because now we have to change our domain model to fit the query model that we want.

Not really. It is not well known, because we don’t generally think about this as an important concept that should be externalized to the users, but while we usually portray NHibernate working on the following model:


This is not actually accurate. What is closer to the way NHibernate works is this model:


And the reason that this is important is that the entity model doesn’t have to match the POCO model.

Let us see how this works:

<set name="Posts"
    <key column ="BlogId"/>
    <one-to-many class="Post"/>

As you can see, we specify a no op access strategy (with NH 2.1 you can also use access=”none”, which sounds nicer), to do so. Now, we can execute a query:

var blog = 
    s.CreateQuery("from Blog b where size(b.Posts) > 5")

Remember, Blog doesn’t have a Posts property, it is a query only property. This code results in:


This is actually most useful when you want to have different projections on the same thing. Let us take a look:

<set name="RecentPosts"
     where="(PostedAt >= (getdate() - 30) )"
    <key column ="BlogId"/>
    <one-to-many class="Post"/>

And using this just as before:

var blog =
       s.CreateQuery("from Blog b where size(b.RecentPosts) > 5")

And that will result in this:


I think that this is the key usage scenario for this feature, being able to create query only associations that I’ll traverse only for querying.


Benny Michielsen

I had no idea this was possible, keep 'em coming!

Dave the Ninja

@Benny - neither did I!!!

@Ayende - Time to refactor some code written last night to do this very thing - time to remove the noisey POCO collection reference!



Krzysztof Kozmic

I imagine using this this will be tricky to implement with LINQ (or strongly named criteria) which assume that Entity Model == POCO model

Shane Courtrille

The world would benefit greatly from a series titled..

"Things you didn't know about NHibernate"

This is awesome :D

Gunnar Liljas

It can be implemented with LINQ if you're not afraid of exposing primary and foreign keys as properties. Not beautiful, but it's actually just a bit of noise.


I guess technically you could have entity types and linq against them.. very hacky though..

Ayende you say: "In our domain model, we don’t want to have a Blog.Posts collection, we want to only have a Blog.Post."

Did you mean Post.Blog? otherwise I don't follow..

And can you explain why you wouldn't want Blog.Posts on the poco? just the example scenario, or good practice? is this related to aggregate roots?

Ayende Rahien

Yes, that was a typo.

And there are a few reasons, most of them relating to the fact that you don't want to have highly connect object models, or that if you would try to create those associations, you would have association explosion


is this working?

select b.Id,



from Blog b

where size(b.RecentPosts) > 5

Min Han

These recent posts on NHibernate are really interesting. I would have no idea how I would have come upon this particular gem without this post.

Richard Dingwall

I didn't know this was possible either, very cool. It looks like it works for version columns too (who cares abouts optimistic locking implementation in the domain model).

I even tried it on an ID column (value type in domain, but has an ID in the legacy relational schema), but that failed with this exception:

NHibernate.HibernateException : identifier of an instance of SMS.Domain.Osm.CoreCompetencyRequirements was altered from 12189 to

:O might log a bug report

Michael Teper

Hmm, that's really interesting, but only as a curiosity. It actually looks like an antipattern to me because the mapping, which is supposed to be an implementation detail is now required to understand query syntax, in addition to the POCO model.

Richard Dingwall

Hmm check that. Noop'd version is not working either.

Gerke Geurts

@Michael Teper: If query implementation is the responsibility of a repository/query service, just like the mapping definition, then I don't see any design conflicts.

Frans Bouma

I really don't understand why anyone would want to add query predicates to a mapping file in XML and use that in a string based query in C#. If something will become a maintenance nightmare this is probably it.

Not having a field mapped onto a relationship is not that uncommon, but mainly in o/r mapper frameworks which do reverse relationship maintenance (i.e. myOrder.Customer = myCustomer; also adds myOrder to myCustomer.Orders), as you sometimes don't want the PK side to know about all the FK sides it has, for example because it's kept in memory and could lead to problems.

As the other side of the relationship does have a field mapped (Post.Blog), isn't that enough to query?

Paul Batum

Hmm, I didn't know you could do that. Not sure how we'll support this one in Fluent NHibernate...

Hendry Luk


It "could" work in strong type criteria, eg NHQG. Doubt it's there though atm.


You say that "there are a few reasons" for not exposing Blog.Posts.

I'm wondering whether one of this reasons is that such one-to-manymany relationships are "dangerous" with regard to performance. Hiding them can reduce the risk of developpers using them and forgetting what happens under the hood. Is it the case ?

Ayende Rahien

That is one of them, for sure. There are also implications from the point of view of the domain model, but mostly it is because a lot of those associations just doesn't really make sense as an association on the objects

Chris Nicola

Interesting, though I may be a bit confused as to the difference between the entity model and the POCO. The POCO is the domain model I take it, but then what is the nature of the mapping from entities to POCOs?

Also, if I were creating a UI using MVVM does that mean I would have yet another mapping of the viewmodel to the POCOs. Seems overkill perhaps, but it is more than likely I am just misunderstanding. I just don't want to get into the mistake of creating redundant code.

Ayende Rahien


That is why this is hidden very deeply inside NHibernate, where you don't usually see it.

From your perspective, you can treat POCO as the final model

Wayne Douglas

I think of this as saying this:

in the EM that we want to have a virtual property mapped one-to-many to another entity. The POCO has no concept of the relationship - only the entity model expressed through config?

I think I get all the concepts here and it's definitely very cool - what I'm struggling with - as were a couple others is why Blog.Posts is a bad idea - seems like the most natural thing in the world to me :s

Is this because, semantically, you think it's wrong to have this relationship?



Chris Nicola

Ah I understand what you're saying now. This is definitely a useful feature I can imagine a number of situations where I could use it.

I feel like I may have made a mistake with my bi-directional associations though. I have a sort of three level tree of one-two many associations where I query the root entities and then load the collections.

Ayende Rahien


Don't look at Blog.Posts, try to think about Blog.RecentPosts, or Blog.PostsByCurrentAuthor, or stuff like that.

Alexander Kovtik

Does noop access strategy work with simple properties (not collections)? I can't get it working...

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats