13

Is there a good explanation out there on what exactly lazy="extra" is capable of?

All the posts I've seen all just repeat the fact that it turns references to MyObject.ItsCollection.Count into select count(*) queries (assuming they're not loaded already).

I'd like to know if it's capable of more robust things, like turning MyObject.ItsCollection.Any(o => o.Whatever == 5) into a SELECT ...EXISTS query.

Section 18.1 of the docs only touches on it. I'm not an NH developer, so I can't really experiment with it and watch SQL Profiler without doing a bit of work getting everything set up; I'm just looking for some sort of reference describing what this feature is capable of.

Thank you!

Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • 1
    When Any() iterates the collection, it does so through the IEnumerable interface. NHibernate have no way of knowing that the iteration is performed by Any() (or Where() or whatever), and thus have no choice but to fetch all elements. It cannot detect the predicate. – Oskar Berggren Sep 11 '12 at 08:22

3 Answers3

20

for version 2.x it is only used to translate a collection.Count() into a select count and as far as i can see in the source, it will also allow the construct collection[5] to fetch that particular entity (with index 5) instead of hydrating the whole collection.

For version 3.x i didn't see anything related in the release notes

Jaguar
  • 5,929
  • 34
  • 48
  • Wow - thanks for checking the source code for me (!!!). Is this documented anywhere, for my own future reference?? – Adam Rackis Feb 22 '11 at 15:58
  • Consider the nhibernate reference as a whitelist (but always read the release notes too, see below): While various other undocumented stuff may work, only what is explicitly named in the reference is a supported feature. So, when the reference says that the extra laziness is for efficient individual element fetching in collections, that's what you should expect. Check 17.1. Fetching strategies. It mentions the individual fetch but not the count 'hack'. However, the release notes include it. Personally i don't use it, its buggy in my scenarios and i prefer the ISession.CreateFilter() mechanism – Jaguar Feb 22 '11 at 16:15
  • Is there any reason why we wouldn't want to set lazy="extra" to everything? I don't see the point why we wouldn't, as there seems no costs associated to using extra instead of just true? – syclee Mar 21 '12 at 01:43
  • 3
    @sp1ky If the collection size is small, and you often access several of its members, lazy=extra will cause additional roundtrips to the DB. – Oskar Berggren Sep 11 '12 at 08:17
5

Just tried calling Any() on a Collection Customer.Orders mapped with lazy="extra"

customer.Orders.Any()

and the resulting SQL statement looked something like this (simplified):

SELECT *
FROM Order
WHERE CustomerId = 120

Whereas when calling

customer.Orders.Count > 0

the resulting SQL looked like this:

SELECT count(*)
FROM Order
WHERE CustomerId = 120
Jakobus
  • 92
  • 1
  • 2
4

The lazy = extra allow to count the element of a collection without needing of fetching it, since the lazy entity is decorated with a proxy, when the client code ask for the .Count on the collection, a proper "select count" query is issued to the database. Without lazy=extra the collection is read from the database.

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
  • Thank you for your answer. I'm aware of the behavior you mentioned. I'm looking for some sort of documentation showing some of the more robust cases it's capable of (if any) - like handling an Any() call and turning it into an EXISTS query. – Adam Rackis Feb 22 '11 at 15:26
  • Sorry for mistooking your question. But afaik the behaviour you described does not apply. Maybe the nh linq provider is capable of. – Felice Pollano Feb 22 '11 at 15:29