Ambient transactions (System.Transactions) play an increasingly
important role in .NET programming. Especially in WCF they are the
preferred transaction model. Hibernate supports ambient transactions
by implementing the IEnlistmentNotification interface. Unfortunately,
ambient transactions can only be used in the same way as ADO.NET
transactions:
using (ISession session = factory.OpenSession()) {
using (TransactionScope scope = new TransactionScope()) {
…
scope.Complete();
}
}
But ambient transactions are designed for distributed scenarios and
are typically used in the following way:
using (TransactionScope scope = new TransactionScope()) {
using (ISession session = factory1.OpenSession()) {
…
} // exception is thrown here
using (ISession session = factory2.OpenSession()) {
…
}
// access some other resource manager
}
When using transacted WCF services, service operations are
automatically enclosed in a (possibly distributed) transaction
context.
But when using NH in this way, one gets an exception when a session is
closed within an active ambient transaction
(InvalidOperationException: "Disconnect cannot be called while a
transaction is in progress."). While this behavior is useful for
ADO.NET transactions (because these transactions are tied to the
connection they are created with), this make less sense for ambient
transactions (because they are totally independent from any
connection).
Therefore, I propose that NH should allow closing a session even
within an active ambient transaction. In this case NH should also
flush the session (and thereby emitting the necessary SQL statements).
Since the implementation of ambient transactions in NH is cleanly
separated from the rest of the NH code, only minor modifications in
AbstractSessionImpl, SessionImpl, and ConnectionManager where
necessary to implement this behavior in a prototypical manner.
I curious about the opinion of the NH community on this issue.
H. Heinzelreiter.