Lesser-Known NHibernate Features: Future Queries
Sometimes it makes sense to send several queries at the same time to the database server. This prevents multiple roundtrips and normally can provide results faster. Knowing this, NHibernate offers two features: multiqueries and future queries. Future queries build upon multiqueries and because they use LINQ, which is probably the most common querying API in NHibernate, I will focus in this.
In order to use future queries, you queue them, by calling the ToFuture() or ToFutureValue() extension methods on any number of queries that you wish to retrieve together:
1: var futureProducts = session.Query<Product>().Where(p => p.Price > 1000)
.ToFuture();
2:
3: var futureCustomers = session.Query<Customer>().Where(c => c.Orders.Any()).ToFuture();
4:
5: //no query is sent to the database
Only after you actually access its results are the queries sent:
1: var productsCount = futureProducts.Count();
And the generated SQL is:
1: select
2: product0_.product_id as product1_6_,
3: product0_.name as name6_,
4: product0_.price as price6_
5: from
6: product product0_
7: where
8: product0_.price>@p0;
9: select
10: customer0_.customer_id as customer1_3_,
11: customer0_.name as name3_,
12: customer0_.email as email3_
13: from
14: customer customer0_
15: where
16: exists (
17: select
18: orders1_.order_id
19: from
20: [
21: order] orders1_ where
22: customer0_.customer_id=orders1_.customer_id
23: );
24: ;
25: @p0 = 1000 [Type: Decimal (0)]
Notice how the two queries are sent at the same time, separated by a semicolon.
It also works for single values, they can be combined with multi value queries:
1: var mostExpensiveFutureProduct = session.Query<Product>()
.OrderByDescending(x => x.Price).Take(1).ToFutureValue();
The caveat is that this, like multiqueries, is right now only supported in SQL Server, Oracle and MySQL. In all the other cases the results will be retrieved immediately.