无法将NServiceBus v5多租户传奇示例设置为托管服务

时间:2017-06-05 17:23:04

标签: c# sql-server nhibernate nservicebus

我查看了NServiceBus文档并运行了用于设置多个租户的示例,以便将saga数据保存在每个租户的各个数据库中。

https://docs.particular.net/samples/outbox/multi-tenant/?version=core_5

我目前有一个使用 NServiceBus.Host 包的NServiceBus应用程序,并作为Windows服务运行。它在几个租户之间共享一个saga数据表,因此认为将样本转换为托管是很简单的,这样我就可以看到我需要如何继续将现有项目转换为多租户SQL连接。但是,该示例使用控制台应用程序和手动创建的总线。

如果我将 NServiceBus.Host NuGet包添加到示例应用程序,则会添加 EndpointConfig.cs 文件,但我无法弄清楚如何工作使用Pipeline Executor。

Program.cs Receiver 项目中,有以下内容:

internal static PipelineExecutor PipelineExecutor;

var busConfiguration = new BusConfiguration();
PipelineExecutor = ((UnicastBus) startableBus).Builder.Build<PipelineExecutor>();

但是,您显然无法在托管应用程序的 EnpointConfig.cs 内执行此操作。

接下来,如果您在调用方法中查看 MultiTenantOpenSqlConnectionBehavior.cs ,则可以访问上下文IncomingContext context,其中各个客户端连接被填充到上下文中它们的相应键和下一个管道步骤通过next();

执行
class MultiTenantOpenSqlConnectionBehavior :
    IBehavior<IncomingContext>
{

    public void Invoke(IncomingContext context, Action next)
    {
        var defaultConnectionString = ConfigurationManager.ConnectionStrings["NServiceBus/Persistence"]
            .ConnectionString;
        #region OpenTenantDatabaseConnection

        string tenant;
        if (!context.PhysicalMessage.Headers.TryGetValue("TenantId", out tenant))
        {
            throw new InvalidOperationException("No tenant id");
        }
        var connectionString = ConfigurationManager.ConnectionStrings[tenant]
            .ConnectionString;
        var lazyConnection = new Lazy<IDbConnection>(() =>
        {
            var connection = new SqlConnection(connectionString);
            connection.Open();
            return connection;
        });
        var key = $"LazySqlConnection-{defaultConnectionString}";
        context.Set(key, lazyConnection);
        try
        {
            next();
        }
        finally
        {
            if (lazyConnection.IsValueCreated)
            {
                lazyConnection.Value.Dispose();
            }
            context.Remove(key);
        }

        #endregion
    }
}

然后在 MultiTenantConnectionProvider.cs 中,引用上面声明的静态 PipelineExecutor ,并且使用该上下文可以使用上述类中设置的相同键检索连接

class MultiTenantConnectionProvider :
    DriverConnectionProvider
{

    public override IDbConnection GetConnection()
    {
        var defaultConnectionString = ConfigurationManager.ConnectionStrings["NServiceBus/Persistence"]
            .ConnectionString;

        #region GetConnectionFromContext

        Lazy<IDbConnection> lazy;

        //
        // This line is the problem. The static Program.PipelineExecutor is accessed
        //
        var pipelineExecutor = Program.PipelineExecutor;

        var key = $"LazySqlConnection-{defaultConnectionString}";
        if (
            pipelineExecutor != null &&
            pipelineExecutor.CurrentContext.TryGet(key, out lazy))
        {
            var connection = Driver.CreateConnection();
            connection.ConnectionString = lazy.Value.ConnectionString;
            connection.Open();
            return connection;
        }
        return base.GetConnection();

        #endregion
    }
}

当然,必须有一种方法可以在托管应用程序中执行此操作,但我找不到有关如何执行此操作的任何信息。

1 个答案:

答案 0 :(得分:0)

不幸的是,NServiceBus主机不支持多租户方案。相反,您可以将该示例使用自托管服务https://docs.particular.net/nservicebus/hosting/windows-service

代码相当简单