This is a common question, but the explanations found so far and observed behaviour are some way apart.
We have want the following nHibernate strategy in our MVC website:
SessionScope
for the request (to track changes)ActiveRecord.TransactonScope
to wrap our inserts only (to enable rollback/commit of batch)Now currently we:
SessionScope
(with FlushAction Auto or Never)ActiveRecord.TransactionScope
there is no delayed flush and any contained selects are also caught up in a long-running transaction.I'm wondering if it's because we have an old version of nHibernate (it was from trunk very near 2.0).
We just can't get the expected nHibernate behaviour, and performance sucks (using NHProf and SqlProfiler to monitor db locks).
Here's what we have tried since:
ActiveRecord.TransactionScope
on the Commit, not in the ctor
(delays transaction until needed)ctor
if none are available (as a guard)insert
/update
outside of the Transaction (!)Now we have the following application behaviour:
SELECT
s needed by services are fired, all outside a transactionRepository.Add
calls do not hit the db until scope.Commit
is called in our ControllersINSERT
s / UPDATE
s occur wrapped inside a transaction as an atomic unit, with no SELECT
s contained.... But for some reason nHProf now != sqlProfiler (select
s seems to happen in the db before nHProf reports it).
NOTE
Before I get flamed I realise the issues here, and know that the SELECTs aren't in the Transaction. That's the design. Some of our operations will contain the SELECTs (we now have a couple of our own TransactionScope
implementations) in serialised transactions. The vast majority of our code does not need up-to-the-minute live data, and we have serialised workloads with individual operators.
ALSO
If anyone knows how to get an identity column (non-PK) refreshed post-insert
without a need to manually refresh the entity, and in particular by using ActiveRecord markup (I think it's possible in nHibernate mapping files using a 'generated' attribute) please let me know!!