Saga Persister

Component: Sql Persistence
NuGet Package NServiceBus.Persistence.Sql (2.x)
Target NServiceBus Version: 6.x

SQL Persistence supports sagas using the Core NServiceBus.Saga API or an experimental API unique to SQL Persistence that provides a simpler mapping API.

In order to use the NServiceBus Core Saga<T> base class for sagas, use SQL Persistence Version 3.2 or above.

Table Structure

Table Name

The name used for a saga table consist of two parts.

  • The prefix of the table name is the Table Prefix defined at the endpoint level.
  • The suffix of the table name is either the saga Type.Name or, if defined, the Table Suffix defined at the saga level.
class MySaga:SqlSaga<MySaga.SagaData>
{
    protected override string TableSuffix => "TheCustomTableName";
Using Delimited Identifiers in the TableSuffix is currently not supported.

Columns

Id

The value of IContainSagaData.Id. Primary Key.

Metadata

Json serialized dictionary containing all NServiceBus managed information about the Saga.

Data

Json serialized saga data

PersistenceVersion

The Assembly version of the SQL Persister.

SagaTypeVersion

The Assembly version of the Assembly where the Saga exists.

Correlation Ids

There is between 0 and 2 correlation id columns named Correlation_[PROPERTYNAME]. The type will correspond to the .NET type of the mapped property on the saga data.

For each Correlation Id there will be a corresponding index named Index_Correlation_[PROPERTYNAME].

Correlation Ids

Saga Message Correlation is implemented by promoting the correlation property to the level of a column on the saga table. So when a saga data is persisted the correlation property is copied from the instance and duplicated in a column named by convention (Correlation_[PROPERTYNAME]) on the table.

In this version of SQL Persistence, a SqlSaga base class must be used to specify the correlation property.

Correlation Types

Each correlation property type has an equivalent SQL data type.

Microsoft SQL Server

CorrelationPropertyTypeSql Type
Stringnvarchar(200)
DateTimedatetime
DateTimeOffsetdatetimeoffset
Intbigint
Guiduniqueidentifier

MySQL

CorrelationPropertyTypeSql Type
Stringvarchar(200) character set utf8mb4
DateTimedatetime
Intbigint(20)
Guidvarchar(38) character set ascii

Oracle

CorrelationPropertyTypeSql Type
StringNVARCHAR2(200)
DateTimeTIMESTAMP
IntNUMBER(19)
GuidVARCHAR2(38)

The following .NET types are interpreted as CorrelationPropertyType.Int:

Json.net Settings

Custom Settings

Customizes the instance of JsonSerializerSettings used for serialization.

var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto,
    Converters =
    {
        new IsoDateTimeConverter
        {
            DateTimeStyles = DateTimeStyles.RoundtripKind
        }
    }
};
var persistence = endpointConfiguration.UsePersistence<SqlPersistence>();
var sagaSettings = persistence.SagaSettings();
sagaSettings.JsonSettings(settings);

Version / Type specific deserialization settings

The Type and Saga Assembly version are persisted. It is possible to explicitly control the deserialization of sagas based on Version and/or Type. This allows the serialization approach to be evolved forward while avoiding migrations.

var currentSettings = new JsonSerializerSettings
{
    DateFormatHandling = DateFormatHandling.IsoDateFormat
};
var settingForVersion1 = new JsonSerializerSettings
{
    DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
var persistence = endpointConfiguration.UsePersistence<SqlPersistence, StorageType.Sagas>();
var sagaSettings = persistence.SagaSettings();
sagaSettings.JsonSettings(currentSettings);
sagaSettings.JsonSettingsForVersion(
    builder: (type, version) =>
    {
        if (version < new Version(2, 0))
        {
            return settingForVersion1;
        }
        // default to what is defined by persistence.JsonSettings()
        return null;
    });

Custom Reader

Customize the creation of the JsonReader.

var persistence = endpointConfiguration.UsePersistence<SqlPersistence>();
var sagaSettings = persistence.SagaSettings();
sagaSettings.ReaderCreator(
    readerCreator: textReader =>
    {
        return new JsonTextReader(textReader);
    });

Custom Writer

Customize the creation of the JsonWriter.

var persistence = endpointConfiguration.UsePersistence<SqlPersistence>();
var sagaSettings = persistence.SagaSettings();
sagaSettings.WriterCreator(
    writerCreator: builder =>
    {
        var writer = new StringWriter(builder);
        return new JsonTextWriter(writer)
        {
            Formatting = Formatting.None
        };
    });

Samples

Related Articles


Last modified