Getting Started
Architecture
NServiceBus
Transports
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Modernization
Samples

SQL Persistence Upgrade Version 8 to 9

Component: Sql Persistence

Script generation via source generators

In version 9, the script generation that creates SQL scripts for sagas at compile time now uses Roslyn as the engine for analyzing saga classes instead of Mono.Cecil. This change carries two consequences:

  1. Roslyn source generators cannot be disabled, otherwise the assembly-level attributes generated by the source generator won't exist, causing the MSBuild task that generates the SQL script files to not generate anything.
  2. Sagas authored with Visual Basic .NET are not supported, as there is currently insufficient evidence of the use of VB.NET sagas to warrant a separate VB.NET source generator. If affected by this change, contact support.

SqlSaga class deprecated

The SqlSaga<T> base class, an alternate base class for defining a saga, is deprecated with a warning starting in NServiceBus.Persistence.Sql version 8.3.0 and generates an error in version 9.0.0.

The SqlSaga class existed primarily to make it easier to identify a saga's correlation ID so that it could be used to generate SQL scripts for saga classes, and to provide a simplified (but experimental) mapping syntax that was ultimately made unnecessary by improvements to the main NServiceBus saga mapping syntax. SqlSaga also did not benefit from the Roslyn analyzers and code fixes for sagas that help ensure sagas don't fall into various antipatterns.

Converting SqlSaga

Each SqlSaga<T> will define a ConfigureMapping method and override the CorrelationPropertyName, such as:

// SQL Persistence SqlSaga<T>
protected override void ConfigureMapping(IMessagePropertyMapper mapper)
{
    mapper.ConfigureMapping<StartOrder>(message => message.OrderId);
    mapper.ConfigureMapping<CompleteOrder>(message => message.OrderId);
}

protected override string CorrelationPropertyName => nameof(MySagaData.OrderId);

Instead, use the NServiceBus.Saga<TSagaData> base class, and express the same mappings together by overriding the ConfigureHowToFindSaga method. Note how the calls to ToMessage<TMessage>(…) can be chained:

// NServiceBus Saga<TSagaData>
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<MySagaData> mapper)
{
    mapper.MapSaga(sagaData => sagaData.OrderId)
        .ToMessage<StartOrder>(message => message.OrderId)
        .ToMessage<CompleteOrder>(message => message.OrderId);
}

A SqlSaga may also override the TransitionalCorrelationPropertyName property to generate a SQL table that can facilitate transitioning from one correlation property to a new strategy. This feature can still be used via the [SqlSaga] attribute:

[SqlSaga(transitionalCorrelationProperty: nameof(MySagaData.LegacyOrderId))]
public class MySaga : Saga<MySagaData>
{
    // Saga implementation
}

Additionally, a SqlSaga may override the TableSuffix property to control the name of the table that is created by the SQL scripts. This can also be accomplished using the [SqlSaga] attribute:

[SqlSaga(tableSuffix: "CustomSagaDataTableName")]
public class MySaga : Saga<MySagaData>
{
    // Saga implementation
}

Related Articles

  • SQL Persistence
    A persister that targets relational databases, including SQL Server, Oracle, MySQL, PostgreSQL, AWS Aurora MySQL and AWS Aurora PostgreSQL.
  • Upgrade Version 9 to 10
    Instructions on how to upgrade NServiceBus from version 9 to version 10.