SQL components enhancement release available

Hi everyone,

We’ve just released NServiceBus.NHibernate 8.4.2, NServiceBus.Persistence.Sql 6.0.1, and NServiceBus.SqlServer 6.1.1.

Outbox with pessimistic concurrency control

In the previous version of the persisters, the Outbox records were always stored only after all message handlers executed. This design is prone to optimistic concurrency failures. While these failures do not cause problems for the transactional logic that operates on the database via Synchronized Storage Session, they cause issues when message handlers have non-transactional side effects (such as sending an e-mail) that can’t be rolled back. In these scenarios, it is desired to use a pessimistic concurrency control strategy to minimize the likelihood of extra handler executions. It is now possible to enable the pessimistic concurrency control for Outbox in NServiceBus.NHibernate 8.4.2 and NServiceBus.Persistence.Sql 6.0.1 through following API:

var outboxSettings = endpointConfiguration.EnableOutbox();

outboxSettings.UsePessimisticConcurrencyControl();

TransactionScope in the Outbox

The main use case for the Outbox is to provide exactly-once message processing in environments with no distributed transaction (DTC) support. So far it wasn’t possible to use the Outbox in scenarios were the transport did not support DTC but the Outbox and the business data stores could enlist in distributed transactions eg. on-premises systems running over RabbitMQ with outbox records and business data in separate SQL Server instances. This is now possible in NServiceBus.NHibernate 8.4.2 and NServiceBus.Persistence.Sql 6.0.1 through following API:

var outboxSettings = endpointConfiguration.EnableOutbox();

outboxSettings.UseTransactionScope();

Storage session in DI container

It is a quite common setup to share SqlConnection or ISession (in case of the NHibernate persister) between the NServiceBus persistence and the application data access code. So far, this was possible by only accessing the Synchronized Storage Session on the IMessageHandlerContext. With this release, Synchronized Storage Session is also registered in the NServiceBus built-in dependency injection infrastructure so it can be injected into message handlers or any types referenced by message handlers.

To avoid having to reference NServiceBus persistence in the application data access code, the dependency injection infrastructure can be configured to inject selected properties of the storage session directly into user components:

config.RegisterComponents(c =>
{
    c.ConfigureComponent(b =>
    {
        var session = b.Build<ISqlStorageSession>();
        return new ReceiverDataContext(session.Connection, session.Transaction);
    }, DependencyLifecycle.InstancePerUnitOfWork);
});

You can see this working in the Entity Framework and Entity Framework Core samples.

User-provided transactions in the transport

The SQL Server transport supports user provided transactions. This feature has been available since version 4.0 but now we enhanced it with additional options. First, it’s possible to provide user transactions to both Send and Publish. Second, user transactions can be used both with IMessageSession, as well as inside message handler code. Finally, there is an option to pass SqlConnection (instead of SqlTransaction) that will be used by the transport operations:

sendOptions.UseCustomSqlConnection(connection);

await context.Send(new Message(), sendOptions);

This last option is useful especially when the connection passed has been previously enlisted in a TransactionScope.

Other enhancements and bug-fixes

This release comes with more enhancements. You can find the full list of changes in the release notes:

Where to get it

You can install the new versions from NuGet: NServiceBus.Transport.SqlServer, NServiceBus.NHibernate and NServiceBus.Persistence.Sql.

With thanks,
The team in Particular

Please read our release policy for more details. Follow @ParticularNews to be notified of new releases and bug fixes.