Service Fabric Persistence Transaction Sharing

Component: Service Fabric Persistence | Nuget: NServiceBus.Persistence.ServiceFabric (Version: 1-pre)
Target NServiceBus Version: 6.x
This page targets a pre-release version and is subject to change prior to the final release.

The current storage transaction is exposed via the SynchronizedStorageSession property on the IMessageHandlerContext implementation. The transaction can be used to ensure atomicity of operations performed by both the business logic and the persister. When running endpoints with the Outbox feature turned on the same transaction will be used for any outgoing messages as well.

Using in a Handler

Edit
public class HandlerThatUsesSession : IHandleMessages<Message>
{
    public async Task Handle(Message message, IMessageHandlerContext context)
    {
        var session = context.SynchronizedStorageSession.ServiceFabricSession();
        var stateManager = session.StateManager;
        var transaction = session.Transaction;
        var dictionary = await stateManager.GetOrAddAsync<IReliableDictionary<string, string>>(transaction, "state")
            .ConfigureAwait(false);
        await dictionary.AddOrUpdateAsync(transaction, "key", _ => "value", (_, __) => "value")
            .ConfigureAwait(false);
    }
}

Using in a Saga

Other than interacting with its own internal state, a saga should not access a database, call out to web services, or access other resources. See Accessing databases and other resources from a saga.

If the situation is special enough to warrant going against this recommendation, the following documentation will describe how to do so.

Edit
public class SagaThatUsesSession : Saga<SagaThatUsesSession.SagaData>,
    IHandleMessages<Message>
{
    public async Task Handle(Message message, IMessageHandlerContext context)
    {
        var session = context.SynchronizedStorageSession.ServiceFabricSession();
        var stateManager = session.StateManager;
        var transaction = session.Transaction;
        var dictionary = await stateManager.GetOrAddAsync<IReliableDictionary<string, string>>(transaction, "state")
            .ConfigureAwait(false);
        await dictionary.AddOrUpdateAsync(transaction, "key", _ => "value", (_, __) => "value")
            .ConfigureAwait(false);
    }
Shared transaction should not be committed (CommitAsync()) or disposed (Dispose()) in the handler or the saga. When data needs to be persisted to a custom collection during handler or saga execution, a new transaction should be created using the StateManager property of the incoming session.
Edit
public async Task Handle(Message message, IMessageHandlerContext context)
{
    var session = context.SynchronizedStorageSession.ServiceFabricSession();
    var stateManager = session.StateManager;
    using (var transaction = stateManager.CreateTransaction())
    {
        var dictionary = await stateManager.GetOrAddAsync<IReliableDictionary<string, string>>(transaction, "specialCollection")
            .ConfigureAwait(false);
        await dictionary.AddOrUpdateAsync(transaction, "key", _ => "value", (_, __) => "value")
            .ConfigureAwait(false);
        await transaction.CommitAsync()
            .ConfigureAwait(false);
    }
}

Last modified