Yes this is exactly what I wanted to do... Except:
My BL is part of a SOA architecture where messages come in via WSE 2.0. All busniness action implement an interface IBusinessAction:
public interface IBusinessAction
{
SoapEnvelope Execute(SoapEnvelope envelope);
}
They all have the following constructor:
public BABase()
{
_adapter = CreateDataAccessAdapter();
_myAdapter = true;
}
public BABase(IDataAccessAdapter adapter)
{
_adapter = adapter;
_myAdapter = false;
}
Originally I had the atomic transactions as you coded above... BUT SOA is so "CRAP" that I had to implement reliable messaging layer on top in order to ensure that the BL was receiving messages "Exactly Once".
SoapEnvelopes are queued on the way in and the dequeue operation is part of the transaction. The InProc transport on the other hand does not start a transaction since it calls the BL directly and there is no inbound queue.
Throw into the mix a load of NMock stubs and 500+ NUnit tests and the thought of the refactor makes me want to cry... (even with ReSharper to hand)
Who's idea was SOA anyway!
But in essence you are entirely correct in that it is possible to ensure the transaction is always started on the same layer and the retry logic can be implemented there. This is just a design issue in my code that I will have to sort out shortly...