NHibernate and Future Queries
Posted by Davy Brion on January 25th, 2009
As some of you already know, i’m a big fan of avoiding excessive roundtrips by batching queries and/or service calls. For NHibernate, i wrote the QueryBatcher class which makes this pretty easy to do. Ayende recently added a much easier approach for this to NHibernate.
Take a look at the following code:
using (ISession session = sessionFactory.OpenSession())
{
// this executes the first query
var categories = session.CreateCriteria(typeof(ProductCategory)).List();
// this executes the second query
var suppliers = session.CreateCriteria(typeof(Supplier)).List();
foreach (var category in categories)
{
// do something
}
foreach (var supplier in suppliers)
{
// do something
}
}
This is a really trivial example, but it should be more than sufficient. It simply executes two very simple queries and loops through the results to do something with each returned entity. The problem, obviously, is that this hits the database twice while there really is no good reason for doing so.
With the new Future feature we can rewrite that code like this:
using (ISession session = sessionFactory.OpenSession())
{
// this creates the first query
var categories = session.CreateCriteria(typeof(ProductCategory)).Future<ProductCategory>();
// this creates the second query
var suppliers = session.CreateCriteria(typeof(Supplier)).Future<Supplier>();
// this causes both queries to be sent in ONE roundtrip
foreach (var category in categories)
{
// do something
}
// this doesn't do anything because the suppliers have already been loaded
foreach (var supplier in suppliers)
{
// do something
}
}
Apart from the comments, did you spot the difference? Instead of calling ICriteria’s List method (which causes the query to be executed immediately), we call ICriteria’s Future method. This returns an IEnumerable of the type you provided to the Future method. And this is where it gets interesting. Instead of executing the queries immediately, the queries are added to an instance of NHibernate’s already existing MultiCriteria class. Only once you enumerate through one of the retrieved IEnumerables will all the (queued) Future queries be executed, in a single roundtrip. Once they are executed, their result is final (as in: enumerating through the IEnumerable will not cause the query to be executed again).
The example used here is obviously very trivial, but you can use this with any ICriteria so you can very easily start batching your complex queries as well. The kind of query doesn’t really matter, as long as it’s an ICriteria instance.
This feature will be available in NHibernate 2.1, or if you’re using the trunk you can use it starting with revision 3999.
January 29th, 2009 at 10:18 pm
[...] examples adapted from Davy Brion posts [1] and [...]
January 30th, 2009 at 4:09 pm
[...] examples adapted from Davy Brion posts [1] and [2]. Posted ene 30 2009, 01:10 p.m. by Dario Quintana Filed under: querying, HQL, Criteria, [...]
April 13th, 2009 at 8:08 pm
[...] blogged about NHibernate’s Future queries a couple of times already. But as you know, NHibernate aims to offer you a way to write your code completely [...]
November 16th, 2009 at 7:50 pm
[...] Former ECer Davy Brion, as always, does an excellent job of demonstrating usage of the feature here so I am not going to rehash that. What I am going to focus on here if the [...]
November 21st, 2009 at 7:44 am
u have mentioned in the above eg with Using keyword
using (ISession session = sessionFactory.OpenSession())
will the session object here be disposed once it leaves the using Scope or will i have to manually close the session object by telling Session.Close()
November 21st, 2009 at 10:21 am
@Prasobh
calling Dispose on the ISession interface will indeed close the session
February 4th, 2010 at 11:08 pm
How about the names of parameters in Future Queries? I have a big problem in combining queries with the same parameter name.
February 5th, 2010 at 10:51 am
@stepan
that’s a problem that only occurs with HQL queries… but it has been fixed already and the fix will be in NH3.0:
http://nhjira.koah.net/browse/NH-2084