﻿# RavenDB Persistence

<!-- Version variant: raven_10; default: [/persistence/ravendb/index.md](/persistence/ravendb/index.md) -->


Uses the [RavenDB document database](https://ravendb.net/) for storage.


## Persistence at a glance

For a description of each feature, see the [persistence at a glance legend](/persistence/index.md#persistence-at-a-glance).

|Feature                    |   |
|:---                       |---
|Supported storage types    |Sagas, Outbox, Subscriptions
|Transactions               |via `IAsyncDocumentSession.SaveChangesAsync()` or cluster-wide transactions
|Concurrency control        |Pessimistic concurrency, optional optimistic concurrency
|Scripted deployment        |Not supported
|Installers                 |None. Required indexes are created in the database as needed.

## RavenDB versions

Specific versions of RavenDB Persistence are tied to a major version of NServiceBus and also designed to work with a specific version of the RavenDB client library. When releasing a new major version of NServiceBus, the corresponding RavenDB Persistence release will use the last supported version of RavenDB, so that it is never necessary to upgrade both NServiceBus and RavenDB at the same time.

See the [NServiceBus Packages Supported Versions](/nservicebus/upgrades/supported-versions.md#persistence-packages-nservicebus-ravendb) to see the support details for each version of RavenDB Persistence.

RavenDB clients are compatible with their corresponding server version and newer versions:

- [FAQ: Backward Compatibility | RavenDB 6.2 Documentation](https://ravendb.net/docs/article-page/6.2/csharp/client-api/faq/backward-compatibility#ravendb-4.2-and-higher-compatibility)

#### Example

NServiceBus.RavenDB 9.0 uses RavenDB.Client v5.4.116.* which is compatible with RavenDB Server 5.4, 6.0, 6.1.x, 6.2.x, 7.0.x, and future newer versions of RavenDB Server

## Connection options for RavenDB

There are a variety of options for configuring the connection to a RavenDB Server. See [RavenDB Connection Options](connection.md) for more details.

## Shared session

NServiceBus supports sharing the same RavenDB document session between Saga persistence, Outbox persistence, and business data, so that a single persistence transaction can be used to persist the data for all three concerns atomically. Shared sessions are automatically configured when an endpoint has enabled the [Outbox feature](/nservicebus/outbox/index.md) or contains [sagas](/nservicebus/sagas/index.md).

To use the shared session in a message handler:

<!-- snippet: ravendb-persistence-shared-session-for-handler -->

```cs
public class HandlerThatUsesSession :
    IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        var document = new MyDocument();
        var ravenSession = context.SynchronizedStorageSession.RavenSession();
        return ravenSession.StoreAsync(document, context.CancellationToken);
    }
}
```

<!-- endsnippet -->

Although additional database operations inside a saga handler are not recommended (see warning below), the shared session can also be accessed from a saga handler:

> [!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: ravendb-persistence-shared-session-for-saga -->

```cs
public class SagaThatUsesSession :
    Saga<SagaThatUsesSession.SagaData>,
    IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        var document = new MyDocument();
        var ravenSession = context.SynchronizedStorageSession.RavenSession();
        return ravenSession.StoreAsync(document, context.CancellationToken);
    }
```

<!-- endsnippet -->


## Customizing the IAsyncDocumentSession

The creation of the RavenDB `IAsyncDocumentSession` instance used by NServiceBus and made available as the [shared session](#shared-session) can be customized as shown in the following snippet. Despite the name of the method, this option *does not enable the shared session* but only affects the customization of that session.

<!-- snippet: ravendb-persistence-customize-document-session -->

```cs
var documentStore = new DocumentStore();
// configure documentStore here
var persistence = endpointConfiguration.UsePersistence<RavenDBPersistence>();
persistence.UseSharedAsyncSession(
    getAsyncSessionFunc: headers =>
    {
        var session = documentStore.OpenAsyncSession();
        // customize session here
        return session;
    });
```

<!-- endsnippet -->

> [!NOTE]
> When the RavenDB `DocumentStore` is created by the user at endpoint configuration time, it's important to dispose it by calling the `Dispose()` method, before shutting down the endpoint process.


## Multi-tenant support

It is possible to select the database used to store NServiceBus-related data, such as saga data and outbox records, based on information stored in the incoming message headers:

<!-- snippet: multi-tenant-support -->

```cs
var persistence = endpointConfiguration.UsePersistence<RavenDBPersistence>();
persistence.SetMessageToDatabaseMappingConvention(headers =>
{
    //based on incoming message headers select the correct RavenDB Database
    return "selected-database-name";
});
```

<!-- endsnippet -->


## Viewing the data

Open a web browser and type the URL of the RavenDB server. This opens the [RavenDB Studio](https://ravendb.net/docs/search/latest/csharp?searchTerm=management-studio).


## Migrating timeouts

Timeouts can be migrated to the native-delay delivery implementation with the [migration tool](/nservicebus/tools/migrate-to-native-delivery.md).
