Transaction configuration changes in Version 6

Component: NServiceBus

Version 6 provide a configuration API that is more aligned with the transaction capabilities of the transport.

Enabling transactions

Transactions are enabled by default so calls to .Enable() can safely be removed.

6.x NServiceBus
Edit
// Using a transport will enable transactions automatically.
endpointConfiguration.UseTransport<MyTransport>();
5.x NServiceBus
Edit
var transactionSettings = busConfiguration.Transactions();
transactionSettings.Enable();

Disabling transactions

Disabling transactions is now done by setting a transport transaction mode.

6.x NServiceBus
Edit
var transport = endpointConfiguration.UseTransport<MyTransport>();
transport.Transactions(TransportTransactionMode.None);
5.x NServiceBus
Edit
var transactionSettings = busConfiguration.Transactions();
transactionSettings.Disable();

Enabling distributed transactions

Distributed transactions is the default mode for transports with DTC support but can be enabled explicitly.

6.x NServiceBus
Edit
var transport = endpointConfiguration.UseTransport<MyTransport>();
transport.Transactions(TransportTransactionMode.TransactionScope);
5.x NServiceBus
Edit
var transactionSettings = busConfiguration.Transactions();
transactionSettings.EnableDistributedTransactions();

Disabling distributed transactions

Disabling distributed transactions is now done by setting a transport transaction mode.

6.x NServiceBus
Edit
var transport = endpointConfiguration.UseTransport<MyTransport>();
transport.Transactions(TransportTransactionMode.ReceiveOnly);
5.x NServiceBus
Edit
var transactionSettings = busConfiguration.Transactions();
transactionSettings.DisableDistributedTransactions();

Or, if the transport supports native AtomicWithReceive:

6.x NServiceBus
Edit
var transport = endpointConfiguration.UseTransport<MyTransport>();
transport.Transactions(TransportTransactionMode.SendsAtomicWithReceive);

Controlling transaction scope options

Version 6 allows transaction scope options to be configured at the transport level. Setting isolation level and timeout can now be done with the following:

6.x NServiceBus
Edit
var transport = endpointConfiguration.UseTransport<MyTransport>();
transport.Transactions(TransportTransactionMode.TransactionScope);
transport.TransactionScopeOptions(
    isolationLevel: IsolationLevel.RepeatableRead,
    timeout: TimeSpan.FromSeconds(30));
5.x NServiceBus
Edit
var transactionSettings = busConfiguration.Transactions();
transactionSettings.IsolationLevel(IsolationLevel.RepeatableRead);
transactionSettings.DefaultTimeout(TimeSpan.FromSeconds(30));

Wrapping handlers execution in a transaction scope

Version 6 comes with a unit of work that wraps execution of handlers in a transaction scope, which can now be done with this API:

6.x NServiceBus
Edit
var unitOfWork = endpointConfiguration.UnitOfWork();
unitOfWork.WrapHandlersInATransactionScope();
5.x NServiceBus
Edit
var transactionSettings = busConfiguration.Transactions();
transactionSettings.WrapHandlersExecutionInATransactionScope();

Forwarding messages to error queue when transactions are disabled

When transactions are disabled and if any errors are encountered during the processing of the message then the messages will be forwarded to the error queue. In Version 5, this message would have been lost. For more details, read the new behavior changes in Version 6.

Suppressing the ambient transaction

config.Transactions().DoNotWrapHandlersExecutionInATransactionScope() has been removed since transaction scopes are no longer used by non DTC transports to delay the dispatch of all outgoing operations until handlers have been executed.

In Version 6, handlers will only be wrapped in a TransactionScope if the given transport chooses to do so. Transports that do this in their default configuration include MSMQ and SQL Server. This means that performing storage operations against data sources that also support transaction scopes will escalate to a distributed transaction. Opting out of this behavior can be done with the following:

6.x NServiceBus
Edit
var transport = endpointConfiguration.UseTransport<MyTransport>();
transport.Transactions(TransportTransactionMode.ReceiveOnly);
5.x NServiceBus
Edit
var transactions = busConfiguration.Transactions();
transactions.DoNotWrapHandlersExecutionInATransactionScope();

For more information see Transport transaction - Sends atomic with Receive.

Version 6 leans on native transport transaction and the new batched dispatch support to achieve the same level of consistency with better performance.

Suppressing the ambient transaction created by the MSMQ and SQL Server transports can still be achieved by creating a custom pipeline behavior with a suppressed transaction scope.

Access to runtime settings

The following properties have been obsoleted on TransactionSettings class.

SuppressDistributedTransactions

To determine if distributed transactions are suppressed.

6.x NServiceBus
Edit
var transactionModeForReceives = readOnlySettings.GetRequiredTransactionModeForReceives();
var suppressDistributedTransactions = transactionModeForReceives != TransportTransactionMode.TransactionScope;
5.x NServiceBus
Edit
var suppressDistributedTransactions = transactionSettings.SuppressDistributedTransactions;

IsTransactional

To determine if transactions are enabled.

6.x NServiceBus
Edit
var transactionModeForReceives = readOnlySettings.GetRequiredTransactionModeForReceives();
var isTransactional = transactionModeForReceives != TransportTransactionMode.None;
5.x NServiceBus
Edit
var isTransactional = transactionSettings.IsTransactional;

Last modified