The session cache only caches individual entities; it does not cache queries (e.g. anything retrieved by an IQuery or ICriteria). That's pretty much the end of that as far as session cache goes.
The following only pertains to second-level cache.
Individual entities are only "keyed" in the cached by their IDs (as defined by the <id> element). There is no way to search in the cache any other way; otherwise, you might as well just go to the database.
When you fetch something using an IQuery without setting it to cacheable, the individual entities get cached (in the second level cache). When you issue the same query again, NHibernate can do one of two things:
- Retrieve all the IDs produced by that query and then see if those entities are already cached. If so, use them in the result; if not, issue a separate query to get what it doesn't already have
- Since we are making a trip to the database anyway, just run the query and get everything
Option#1 above obviously does not make sense as you may end up hitting the database twice. Whereas the second option guarantees that you will get what you want in one round trip. NHibernate does, in my opinion, the sensible thing and implements option#2 above.
In a cached query scenario, the link I gave above should have explained it pretty well.