Posted in:

Last month I posted about how to use Rebus with Azure Storage Queues. This allowed you to use the Azure Storage Emulator for local development, and a real Azure Storage Queue account in production. Of course, another benefit of using a messaging abstraction like Rebus is that you can switch transports easily.

In this post I want to explain how we could switch to SQL Server as a transport. It might not seem an obvious choice, but the reason I wanted to try it was to enable local development without needing to run the Azure Storage Emulator. I already had a SQL Server available (and containerized using the technique I wrote about yesterday), and that meant if I could switch Rebus to using that, I could have all my dependencies containerized for local development. This reduces the setup overhead for new developers wanting to work on the project, and also allows for integration tests to be runnable on any server that can host Docker containers. I don't think I would use SQL Server as a transport in production though - it still makes sense to me to use a dedicated messaging service like Azure Service Bus for that.

Instructions

The configuration steps are very similar to those for Azure Storage Queues, so I'll only mention the differences.

First, add a NuGet reference to Rebus.SqlServer.

Next, in the ConfigureServices method for the project that will be listening on the queue, we need to call UseSqlServer with details of the database to use. I've asked it to auto-create the tables used for queue messages.

var transportOptions = new SqlServerTransportOptions(sqlConnectionString);
// possibly the default is true, so this line might not be needed
transportOptions.SetEnsureTablesAreCreated(true);

services.AddRebus((configure, provider) => configure
    .Logging(l => l.MicrosoftExtensionsLogging(
        provider.GetRequiredService<ILoggerFactory>()))
    .Transport(t => t.UseSqlServer(transportOptions, queueName)));

As before, in the Configure method we can start listening with UseRebus:

app.ApplicationServices.UseRebus();

And in the project that sends the message, the configuration is almost identical, except we use UseSqlServerAsOneWayClient and need to set up routing from the message types we're sending to the queue names they should be sent to.

var transportOptions = new SqlServerTransportOptions(sqlConnectionString);

services.AddRebus((configure, provider) => configure
    .Logging(l => l.MicrosoftExtensionsLogging(
        provider.GetRequiredService<ILoggerFactory>()))
    .Transport(t => t.UseSqlServerAsOneWayClient(transportOptions))
    .Routing(r => r.TypeBased().Map<VoteMessage>(queueName))
    );

Summary

The convenience of being able to switch out transports means we can easily use containerized transports for development, testing or even production environments if we want. I showed how to do this with SQL Server since that was most convenient for me as I already had a SQL Server, but Rebus supports several transports and some others that are easily containerized are RabbitMQ, MySql and PostgeSQL.