Simple NHibernate Persistence Usage

Component: NHibernate Persistence
NuGet Package NServiceBus.NHibernate (6.x)
Target NServiceBus Version: 5.x


The samples rely on .\SqlExpress and need the database Samples.NHibernate to run properly.

Code walk-through

This sample shows a simple Client + Server scenario.

  • Client sends a StartOrder message to Server.
  • Server starts an OrderSaga.
  • OrderSaga requests a timeout with a CompleteOrder data.
  • When the CompleteOrder timeout fires the OrderSaga publishes a OrderCompleted event.
  • The Server then publishes a message that the client has subscribed to.
  • Client handles OrderCompleted event.

NHibernate Config

Configure NHibernate with the right driver, dialect and connection string. Since NHibernate needs a form of mapping of the class to the database table, the configuration code also does that with ModelMapper API. Finally, the configuration is used to run the endpoint.

var busConfiguration = new BusConfiguration();

var persistence = busConfiguration.UsePersistence<NHibernatePersistence>();
var nhConfig = new Configuration();

nhConfig.SetProperty(Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider");
nhConfig.SetProperty(Environment.ConnectionDriver, "NHibernate.Driver.Sql2008ClientDriver");
nhConfig.SetProperty(Environment.Dialect, "NHibernate.Dialect.MsSql2008Dialect");
nhConfig.SetProperty(Environment.ConnectionStringName, "NServiceBus/Persistence");



Order Saga Data

Note that to use NHibernate's lazy-loading, all the properties on the Saga data class must be virtual.

public class OrderSagaData :
    public virtual Guid OrderId { get; set; }
    public virtual string OrderDescription { get; set; }

Order Saga

public class OrderSaga :
    static ILog log = LogManager.GetLogger<OrderSaga>();

    protected override void ConfigureHowToFindSaga(SagaPropertyMapper<OrderSagaData> mapper)
        mapper.ConfigureMapping<StartOrder>(message => message.OrderId)
            .ToSaga(sagaData => sagaData.OrderId);

    public void Handle(StartOrder message)
        Data.OrderId = message.OrderId;
        var orderDescription = $"The saga for order {message.OrderId}";
        Data.OrderDescription = orderDescription;
        log.Info($"Received StartOrder message {Data.OrderId}. Starting Saga");

        var shipOrder = new ShipOrder
            OrderId = message.OrderId


        log.Info("Order will complete in 5 seconds");
        var timeoutData = new CompleteOrder
            OrderDescription = orderDescription

        RequestTimeout(TimeSpan.FromSeconds(5), timeoutData);

    public void Timeout(CompleteOrder state)
        log.Info($"Saga with OrderId {Data.OrderId} completed");
        var orderCompleted = new OrderCompleted
            OrderId = Data.OrderId


Handler Using ISession

The handler access the ISession to store business data.

public class ShipOrderHandler :
    ISession session;

    public void Handle(ShipOrder message)
        var orderShipped = new OrderShipped
            Id = message.OrderId,
            ShippingDate = DateTime.UtcNow,


    public ShipOrderHandler(ISession session)
        this.session = session;

The Data in the database

The data in the database is stored in three different tables.

The Saga Data

  • IContainSagaData.Id maps to the OrderSagaData primary-key and unique identifier column Id.
  • IContainSagaData.Originator and IContainSagaData.OriginalMessageId map to columns of the same name of type varchar(255).
  • Custom properties on the SagaData, in this case OrderDescription and OrderId, are also mapped to columns with the same name and of the respecting types.

The Timeouts

  • The subscriber is stored in Destination column and includes Queue and Machine information.
  • The endpoint that initiated the timeout is stored in the Endpoint column.
  • The connected saga ID is stored in a SagaId column.
  • The serialized data for the message is stored in a State column.
  • The scheduled timestamp for the timeout is stored in a Time column.
  • Any headers associated with the timeout are stored in an array of key value pairs stored in the 'Headers' column.

The Subscriptions

Note that the message type maps to multiple subscriber endpoints.

  • The Subscription message type and version are stored in the MessageType column.
  • The list of subscribers is stored in a array of objects each containing Queue and MachineName information.

The Handler Stored data

Related Articles

  • Persistence
    Features of NServiceBus requiring persistence include timeouts, sagas, and subscription storage.
  • Sagas
    NServiceBus uses event-driven architecture to include fault-tolerance and scalability in long-term business processes.

Last modified