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 -~----------~----~----~----~------~----~------~--~---
