Prerequisites
Ensure an instance of MongoDB is running on localhost:27017.
The easiest way to do this is to run MongoDB in Docker:
docker run -d -p 27017:27017 --name TestMongoDB mongo:latest --replSet tr0
docker exec -it TestMongoDB mongosh --eval '
rs.initiate({
_id: "tr0",
members: [{ _id: 0, host: "localhost:27017" }]
})'
Alternatively, it is possible to install MongoDB but the instance must be part of a replica set to enable transactions. If this is not possible, the endpoint configuration must be altered to disable transactions (not recommended for production):
endpointConfiguration.UsePersistence<MongoPersistence>().UseTransactions(false)
Data visualization
To visualize data in MongoDB, install a MongoDB visualization tool, such as Compass. The screenshots in this sample are taken using Compass.
Code walk-through
This sample shows a simple client/server scenario:
Clientsends aStartOrdermessage toServerServerstarts anOrderSagainstanceOrderSagarequests a timeout withCompleteOrderdataCompleteOrdertimeout occurs andOrderSagapublishes anOrderCompletedeventOrderCompletedis delivered toClient, becauseClientis subscribed to that eventClienthandlesOrderCompleted
MongoDB configuration
The Server endpoint is configured to use MongoDB persistence.
var endpointConfiguration = new EndpointConfiguration("Samples.MongoDB.Server");
var persistence = endpointConfiguration.UsePersistence<MongoPersistence>();
persistence.DatabaseName("Samples_MongoDB_Server");
- If a MongoDB URL is not specified, the persistence uses the default of
mongodb:/./ localhost:27017 - If a database name is not specified, the persistence uses the endpoint name as the database name. In this sample the database name is
Samples_MongoDB_Server.
Order saga
public class OrderSaga(ILogger<OrderSaga> logger) :
Saga<OrderSagaData>,
IAmStartedByMessages<StartOrder>,
IHandleTimeouts<CompleteOrder>
{
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<OrderSagaData> mapper)
{
mapper.MapSaga(sagaData => sagaData.OrderId)
.ToMessage<StartOrder>(message => message.OrderId);
}
public Task Handle(StartOrder message, IMessageHandlerContext context)
{
Data.OrderId = message.OrderId;
var orderDescription = $"The saga for order {message.OrderId}";
Data.OrderDescription = orderDescription;
logger.LogInformation("Received StartOrder message {OrderId}. Starting Saga", Data.OrderId);
logger.LogInformation("Order will complete in 5 seconds");
var timeoutData = new CompleteOrder
{
OrderDescription = orderDescription
};
return 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);
}
}
Saga data
The saga data is stored in the ordersagadata collection.
public class OrderSagaData : ContainSagaData
{
public Guid OrderId { get; set; }
public string OrderDescription { get; set; }
}

| Field | Maps to |
|---|---|
_id | IContainSagaData. |
Originator | IContainSagaData. |
OriginalMessageId | IContainSagaData. |
OrderID | OrderSagaData. |
OrderDescription | OrderSagaData. |
_version | Added and managed by the persistence to prevent concurrency issues |