This is sample shows how to use the NServiceBus Messaging Bridge instead of the deprecated SQL Server transport multi-instance mode.
Prerequisites
Ensure an instance of SQL Server (Version 2016 or above for custom saga finders sample, or Version 2012 or above for other samples) is installed and accessible on localhost
and port 1433
. A Docker image can be used to accomplish this by running docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=yourStrong(!)Password' -p 1433:1433 -d mcr.
in a terminal.
Alternatively, change the connection string to point to different SQL Server instance.
At startup each endpoint will create its required SQL assets including databases, tables, and schemas.
The databases created by this sample are NsbSamplesSqlMultiInstanceReceiver
and NsbSamplesSqlMultiInstanceSender
.
Running the project
Start the following projects:
- Sender
- Receiver
- Bridge
Press enter in the Sender's console window to send a new message.
Verifying that the sample works correctly
- The Receiver displays information that an order was submitted.
- The Sender displays information that a response arrived for the same order.
Code walk-through
The sample contains the following projects:
- Sender: A console application responsible for sending the initial
ClientOrder
message and processing the follow-upClientOrderResponse
message. - Receiver: A console application responsible for processing the order message.
- Bridge: A console application responsible for routing messages across the two database instances.
- Messages: A class library containing message definitions.
- Helpers: A class library for creating the databases and schemas.
Sender project
The sender does not store any data. It mimics a front-end system where orders are submitted by the users and passed via the bus to the back-end. It is configured to use the SQL Server transport. Other than that, it is unaware the other endpoint is running on a different database instance.
var endpointConfiguration = new EndpointConfiguration("Samples.SqlServer.MultiInstanceSender");
var routing = endpointConfiguration.UseTransport(new SqlServerTransport(ConnectionString)
{
TransportTransactionMode = TransportTransactionMode.ReceiveOnly
});
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
endpointConfiguration.EnableInstallers();
routing.RouteToEndpoint(typeof(ClientOrder), "Samples.SqlServer.MultiInstanceReceiver");
The sender sends a message to the receiver:
var order = new ClientOrder
{
OrderId = Guid.NewGuid()
};
await endpoint.Send(order);
Receiver project
The receiver mimics a back-end system. It is configured to use the SQL Server transport but has a different connection string from the sender.
var endpointConfiguration = new EndpointConfiguration("Samples.SqlServer.MultiInstanceReceiver");
endpointConfiguration.UseTransport(new SqlServerTransport(ConnectionString)
{
TransportTransactionMode = TransportTransactionMode.ReceiveOnly
});
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
endpointConfiguration.EnableInstallers();
Note that the endpoint configuration contains no routing information, as the response message is a regular reply and NServiceBus, together with the bridge, will take care of all the routing with reply messages. The receiver replies with ClientOrderResponse
back to the sender.
Bridge
The bridge is configured with two transports. As both transports are of the same SqlServerTransport
type, it is required to provide a name to each BridgeTransport
to distinguish between the two in log files.
var receiverTransport = new BridgeTransport(new SqlServerTransport(ReceiverConnectionString))
{
Name = "Receiver",
AutoCreateQueues = true
};
receiverTransport.HasEndpoint("Samples.SqlServer.MultiInstanceReceiver");
var senderTransport = new BridgeTransport(new SqlServerTransport(SenderConnectionString))
{
Name = "Sender",
AutoCreateQueues = true
};
senderTransport.HasEndpoint("Samples.SqlServer.MultiInstanceSender");
bridgeConfiguration.AddTransport(receiverTransport);
bridgeConfiguration.AddTransport(senderTransport);
// .NET 6 does not support distributed transactions
bridgeConfiguration.RunInReceiveOnlyTransactionMode();
Both transports have the endpoints defined on their side and as a result, the bridge will mimic those endpoints on the other side. This way it becomes transparent to actual endpoints on either side that those endpoints are actually bridged.