Hi all!

I recently upgraded a large project from NH2.0.1 to NH2.1.0CR1, which
brought up an issue with System.Transactions.

This is somewhat related to other discussions where the solution is to
replace session.Close() with session.Dispose() when inside
TransactionScopes to allow for NH to postpone Flush() and Close()
until completion of the outer TransactionScope. (For example NH-1744).

I have not created any failing NH test case, but I'll be happy to
contribute one, if you NH Jedis out there agree that there is no
alternative solution to my problem. (Or that I just have got it all
plain wrong... :-) )

Description of the problem:
Imagine two consecutive TransactionScopes participating in an outer
TransactionScope. They each have their own session and scope #2 wants
to access a resource that scope #1 has updated.
NHibernate suspends session and connection.Close() on scope #1 until
end of the outer TransactionScope and scope #2 will not be able to
access any resource that session #1 is locking. This is expected, and
works exacly the same way in pure ADO.Net when forgetting to do a
connection.Close inside the (inner) scopes. The problem is that in
2.1.0 we have no way to make NHibernate close the db-connection in the
first scope, which would allow the resource to be accessed in scope
#2.
session.Close() results in "Disconnect cannot be called while a
transaction is in progress.." (as discussed in NH-1744). A
disconnection here would however would be perfectly valid when running
in an ambient System.Transaction.

I haven't looked into NHibernate internals, but if I understand
everything correctly, NHibernate does this because it treats the
TransactionScope as an "external" Unit Of Work, and that it always
makes sense to wait until final completion to Flush and Close all
sessions. This is fine, as long as not two consecutive sessions use
the same resources.

Now - one could argue that this is just plain wrong and that combining
business logic where session #1 updates data that session #2 later
wants to access is stupid. Though - I still think that NHibernate
should offer an option to close the session and connection inside an
ambient System.Transaction. In 2.0.1 GA this worked well.

Consider this simple pseudo-code example. Now - before all flaming me
for this somewhat simple example. Imagine that the two inner scopes
are actually pieces of transactional business logic in separate
methods that we want to tie together in a greater transactional whole.

1  Begin Outer scope.
2
3       Begin Inner Txscope 1
4               Begin NH session A
5               Update resource A
6               End session A  (session.Dispose())
7       End inner scope 1
8
9       Begin Inner scope 2
10              Begin NH session B
11              Fetch updated resource A // fails since session A still holds
connection open.
12              End Session B (session.Dispose())
13      End inner scope 2
14
15 End Outer scope

This fails on line 11, since the ADO connection from inner scope 1 is
still open.

Makes sense?

I can think of a few ways to get around this.
1. NH offers a way to close a session within an ambient transaction.
The error message on Close() is perfectly valid, but not when ambient
transactions are present.
2. session.Dispose() should do Flush() and Close() when the inner
scope calls Complete().

I'm not sure of the consequences of either of this solutions, and it
is just the first thoughts that crossed by my mind when looking at
this...

Regards!
/Thomas Heder


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to