Hi guys I am still working on the DTC issues with NH that I detailed in my previous post. In particular, all those issues comes up mostly because we didn't test the DTC in true distributed escalation scenario. Now that I am doing this, I am finding a lot of problems.
Attached is a file that demonstrate the source of a lot of them.
The second file is showing the proposed solution, using:
EnlistDuringPrepareRequired
But first, I need to explain how NH's DTC support works.
If we use an NH session within the context of a TransactionScope, we are
going to get enlist the session in the DTC as volatile resource
We make the assumption that the underlying ADO.Net provider is supporting
DTC correctly (not always a valid assumption, see postgres' issues about
this, but there isn't much we can do about this) and registering itself as
the durable resource.
Now, this is the failing test:
using (var tx = new TransactionScope())
using (var s = sessions.OpenSession())
{
new ForceEscalationToDistributedTx();
s.Delete(s.Get<Person>(id));
tx.Complete();
}
The sequence of event is:
1/ load object from db
2/ register object for deletion
3/ complete transaction
4/ dispose session
5/ dispose transaction
5.1/ call session.Prepare()
5.2/ here we flush the changes to the database
the problem is in 5.2, at this point, _if_ we are in escalated transaction,
and if we are using this approach, we cannot call to the DB again.
That is ecause at this point we are outside the scope of the transaction -
first file shows this.
As I can see this, we have a few options here:
1/ use EnlistDuringPrepareRequired, which is my temporary solution to this.
2/ move the actual flush behavior into the dispose (only on DTC sessions).
The cleanest solution by far is 1, but it means that e cannot use the single
phase enlistment optimization, unfortunately.
I would like to solicit some additional opinions about that.
Program.cs
Description: Binary data
Program.cs
Description: Binary data
