In order to use the transactional session feature with RavenDB persistence, add a reference to the NServiceBus.
NuGet package.
Configuration
To enable the transactional session feature:
var persistence = config.UsePersistence<RavenDBPersistence>();
persistence.EnableTransactionalSession();
Opening a session
To open a RavenDB transactional session:
using var childBuilder = builder.CreateChildBuilder();
var session = childBuilder.Build<ITransactionalSession>();
await session.Open(new RavenDbOpenSessionOptions())
.ConfigureAwait(false);
// use the session
await session.Commit()
.ConfigureAwait(false);
Multi-tenancy support
The specific tenant database name is retrieved from message headers as configured in the SetMessageToDatabaseMappingConvention
-method. This header needs to be set in the options so that the necessary information is available when storing operations and interacting with the outbox.
using var childBuilder = builder.CreateChildBuilder();
var session = childBuilder.Build<ITransactionalSession>();
await session.Open(
new RavenDbOpenSessionOptions(
new Dictionary<string, string>
{
// information is added to the message headers for the
// `SetMessageToDatabaseMappingConvention`-method
{"tenantDatabaseName", "tenantA-databaseName"}
}))
.ConfigureAwait(false);
// use the session
await session.Commit()
.ConfigureAwait(false);
Transaction usage
Message and database operations made via the the transactional session are committed together once the session is committed:
await session.Open(new RavenDbOpenSessionOptions())
.ConfigureAwait(false);
// add messages to the transaction:
await session.Send(new MyMessage())
.ConfigureAwait(false);
// access the database:
var ravenSession = session.SynchronizedStorageSession.RavenSession();
await session.Commit()
.ConfigureAwait(false);
See the RavenDB shared session documentation for further details about using the transaction.
Commit
executes database modifications first and then messages are dispatched with best-effort.