Nels_P_Olsen wrote:
Thinking about it a little more, I suspect the consequence is that NHibernate isn't smart enough to apply criteria in queries to dirty entities in the session, and add them to the result set if they are not found by the underlying SQL query. That really sucks.
Well ... it's not that easy. Actually, in our project we do exactly what you say using our own expression system (using the adapter/wrapper mentioned before; also because NHibernate does not behave "correctly" w.r.t. ORDER BY and MaxResults when doing implicit ploymorphism - see some other thread); but we must hope a little bit that our = operator does the same as e.g. - in our case - SQL Server (which does case-insensitive = in contrast to other databases). There are other examples with type conversions where it is not that easy to mimick the database's behavior.
The next (and IMO biggest) problem are associations: If you need to search for something which has a join to something which is NOT in the session, you'd have to load that associated object - even though the condition might be false! That might kill your performance. Alternatives are splitting the search so that one part happens on the database, one part in memory (what SQL server has to do when you use remote/dsitributed databases). That is VERY complicated ...
So in the end, it's a "design decision" - there is already one engine which can perfectly well do searches by expressions, namely the database; so why conquer huge problems when there is an established concept of how to do it simpler?
Re switching off autoflushing: If you write your business transaction according to the well-known principle "first gather all information, then do the updates", you'll never have a problem when you switch it off (because there are no changes before the reads). However, this principle contradicts clean modularization: "I call a business method here - I don't care whatever it does inside" - it could do its own "read then write" sequence.
The problem mostly comes with loops where later iterations will want to see whether earlier iterations already did something (one example of a "diamond problem", BTW - my belief is that
all problems in software engineering are diamond problems - albeit a little with tongue-in-cheek ;) ). But in such cases, doing an explicit Flush() at the end of the loop (or inner business call) does not hurt and will help.
Thus, my recommendation is to switch off autoflushing in a session with Save() problems and and deal with "funny missing data" on a case-by-case basis - both together will be a rare thing in our experience.
Regards
Harald