NServiceBus outbox with TransactionScope on .Net Core

The transaction scope option for outbox is pretty much useless for .NET Core. When opening a new connection from within a handler it will try to promote the transaction to a distributed transaction even though the connection string is identical to the one used to setup SqlPersistence for the endpoint.
The promotion happens because NServiceBus opens a connection in the incoming pipeline and keeps that open until the message handler is executed.
You should not do that and rather open and close a new connection for each database operation when transaction scope is enabled.

IMO this is a bug in the SqlClient https://github.com/dotnet/SqlClient/issues/13

I think not. That issue was labeled “By design” and closed.

Hi @Tore_Erstad,

could you describe your scenario a bit more?

As mentioned in the documentation the transaction scope with outbox has been designed for scenarios when Outbox records and business data are in separate databases instances and require distributed transactions for atomic commit guarantees.

Cheers,
Tomek

Hi and thank you for answering @tmasternak
In our scenario we are storing business data and outbox data in the same sql server database. We are introducing NServiceBus in an existing code base targeting .NET Core 3.1. The repositories in this code base are newing up connections on demand, using the same connection string as NServiceBus persistence.
This would be an ideal situation for outbox with transaction scope where we could introduce transactional behaviour for both business and outbox data without touching our repositories.
Unfortunately with how NServiceBus keeps an open connection to the database during message handling lifecycle this does not work.
When newing up a new connection from a repository the transaction manager decides to promote to distributed transaction because there is already an open connection - the NServiceBus connection.
There is really no need to promote to distributed transaction when accessing the same sql server database, and it wouldn’t happen if connections were opened in sequence instead of in parallel.
I think it’s a design mistake by NServiceBus to keep an open connection when using transaction scope. Transaction scope could have added value also for single database scenarios if this was changed.

Hi @Tore_Erstad,

thank you for clarifying your scenario. In your scenario, when Outbox and business data are stored in the same database you can take advantage of the synchronized storage session. It is used by SqlPersister (and others) to expose SQL connection and transaction so that these can be used in the handler code to implement unit of work. We have a sample that shows how to do it for EntityFramework DatabaseContext which should be close enough to your scenario I think.

I hope this helps,
Tomek

Yes, we have started using synchronized storage session and have that working, but I think it would be better with the implicit transaction scope approach.
But anyway, we reported the problem, got a fair answer, and understand that you don’t want to change the behavior.
So we will continue with the synchronized storage session approach.

Thanks :slight_smile:

1 Like

Thanks for your feedback @Tore_Erstad :slight_smile: