﻿# Service Fabric Persistence Transaction Sharing


> [!WARNING]
> **NServiceBus.Persistence.ServiceFabric has been sunset**  
> This component is no longer actively developed. We will continue to provide support and address critical fixes during the sunset period, but no new features will be added. If you need help migrating to a different [persistence option](/persistence/index.md#supported-persisters), please contact [support](https://particular.net/support).  
> For information on when this component will reach end of support, see our [support policy page](/nservicebus/upgrades/all-versions.md#persistence-packages-nservicebus-persistence-servicefabric). 


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](/nservicebus/outbox/index.md) feature turned on; the same transaction will be used for any outgoing messages as well.


### Using in a Handler

<!-- snippet: ServiceFabricPersistenceSynchronizedSession-Handler -->

```cs
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");
        await dictionary.AddOrUpdateAsync(transaction, "key", _ => "value", (_, __) => "value");
    }
}
```

<!-- endsnippet -->


### Using in a Saga

> [!WARNING]
> 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](/nservicebus/sagas/index.md#avoid-external-resource-access).

If the situation is special enough to warrant going against this recommendation, the following documentation will describe how to do so.


<!-- snippet: ServiceFabricPersistenceSynchronizedSession-Saga -->

```cs
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");
        await dictionary.AddOrUpdateAsync(transaction, "key", _ => "value", (_, __) => "value");
    }
```

<!-- endsnippet -->

> [!WARNING]
> Shared transaction should not be committed (`CommitAsync()`) or disposed (`Dispose()`) in the handler or the saga.

### Using a custom transaction

When the data needs to be persisted in a custom collection during the handler or saga execution, the action should not participate in the provided transaction. Instead, a new transaction should be created using the `StateManager` property of the incoming session. This is useful when the information needs to be stored regardless of the outcome of the handler's execution.

Service Fabric transactions should be as short-lived as possible and touch only a single resource to reduce lock contention and avoid timeouts.

<!-- snippet: CustomTransaction -->

```cs
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");
        await dictionary.AddOrUpdateAsync(transaction, "key", _ => "value", (_, __) => "value");
        await transaction.CommitAsync();
    }
}
```

<!-- endsnippet -->
