# Simple RavenDB Persistence Usage ## Code walk-through This sample shows a simple Client + Server scenario. 1. `Client` sends a `StartOrder` message to `Server`. 2. `Server` starts an `OrderSaga`. 3. `OrderSaga` requests a timeout with a `CompleteOrder` data. 4. When the `CompleteOrder` timeout fires the `OrderSaga` publishes a `OrderCompleted` event. 5. The Server then publishes a message that the client subscribes to. 6. `Client` handles `OrderCompleted` event. ### Raven Config 1. In the RavenDB studio, create a database named `RavenSimpleSample`. RavenDB does not create the database automatically. 2. Configure the endpoint to use RavenDB persistence. The URL in the `Urls` collection may need to be changed to match the database host/port in use. ```cs var endpointConfiguration = new EndpointConfiguration("Samples.RavenDB.Server"); using var documentStore = new DocumentStore { Urls = ["http://localhost:8080"], Database = "RavenSimpleSample", }; documentStore.Initialize(); var persistence = endpointConfiguration.UsePersistence(); persistence.SetDefaultDocumentStore(documentStore); ``` > [!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. ### Order Saga Data ```cs public class OrderSagaData : ContainSagaData { public Guid OrderId { get; set; } public string OrderDescription { get; set; } } ``` ### Order Saga ```cs public class OrderSaga(ILogger logger) : Saga, IAmStartedByMessages, IHandleTimeouts { protected override void ConfigureHowToFindSaga(SagaPropertyMapper mapper) { mapper.MapSaga(sagaData => sagaData.OrderId) .ToMessage(message => message.OrderId); } public Task Handle(StartOrder message, IMessageHandlerContext context) { var orderDescription = $"The saga for order {message.OrderId}"; Data.OrderDescription = orderDescription; logger.LogInformation("Received StartOrder message {OrderId}. Starting Saga", Data.OrderId); var shipOrder = new ShipOrder { OrderId = message.OrderId }; logger.LogInformation("Order will complete in 5 seconds"); var timeoutData = new CompleteOrder { OrderDescription = orderDescription }; return Task.WhenAll( context.SendLocal(shipOrder), RequestTimeout(context, TimeSpan.FromSeconds(5), timeoutData) ); } public Task Timeout(CompleteOrder state, IMessageHandlerContext context) { logger.LogInformation("Saga with OrderId {OrderId} completed", Data.OrderId); var orderCompleted = new OrderCompleted { OrderId = Data.OrderId }; MarkAsComplete(); return context.Publish(orderCompleted); } } ``` ### Handler Using RavenDB Session The handler accesses the same RavenDB `ISession` via `ISessionProvider`. ```cs public class ShipOrderHandler : IHandleMessages { public Task Handle(ShipOrder message, IMessageHandlerContext context) { var session = context.SynchronizedStorageSession.RavenSession(); var orderShipped = new OrderShipped { OrderId = message.OrderId, ShippingDate = DateTime.UtcNow, }; return session.StoreAsync(orderShipped, context.CancellationToken); } } ``` ## The Data in RavenDB The data in RavenDB is stored in three different collections. > [!WARNING] > By default, this sample uses the [Learning Transport](/transports/learning/index.md), which has built-in support for timeouts and subscriptions. To see the data for timeouts and subscriptions, it's necessary to change the sample to a different transport that does not have these native features such as [MSMQ](/transports/msmq/index.md). ### The Saga Data * `IContainSagaData.Id` maps to the native RavenDB document `Id`. * `IContainSagaData.Originator` and `IContainSagaData.OriginalMessageId` map to simple properties. * Custom properties on the SagaData, in this case `OrderDescription` and `OrderId`, are also mapped to simple properties. ```json { "IdentityDocId": "OrderSagaData/OrderId/33e54adb-10fe-ac05-abdd-a656e8f995b3", "Data": { "$type": "OrderSagaData, Server", "OrderId": "683e7b20-527a-475d-847c-79ef6b0f40a1", "OrderDescription": "The saga for order 683e7b20-527a-475d-847c-79ef6b0f40a1", "Id": "9bf646a0-25b1-4a79-afe3-adf600965476", "Originator": "Samples.RavenDB.Client", "OriginalMessageId": "06cdd874-de9b-40bb-8b90-adf600965448" }, "@metadata": { "@collection": "SagaDataContainers", "Raven-Clr-Type": "NServiceBus.Persistence.RavenDB.SagaDataContainer, NServiceBus.RavenDB", "NServiceBus-Persistence-RavenDB-SagaDataContainer-SchemaVersion": "1.0.0" } } ``` ### The Handler Stored data ```json { "OrderId": "683e7b20-527a-475d-847c-79ef6b0f40a1", "ShippingDate": "2021-12-06T09:07:20.1902988Z", "@metadata": { "@collection": "OrderShippeds", "Raven-Clr-Type": "OrderShipped, Server" } } ```