N服务总线、NHibernate和多租户

N服务总线、NHibernate和多租户,nhibernate,structure,nservicebus,multi-tenant,Nhibernate,Structure,Nservicebus,Multi Tenant,我们正在使用NServiceBus为许多租户执行文档处理 每个租户都有自己的数据库,我们使用NHibernate进行数据访问。在web应用程序中,我们使用IoC工具(StructureMap)来处理会话管理。实际上,我们为每个租户维护一个会话工厂。我们能够从HttpContext中识别租户 当我们使用NServiceBus启动文档处理时,我们可以访问租户标识符。我们需要在文档的整个处理过程中都能使用这个租户id(我们有两个传奇故事,并引发了许多事件) 我们需要为每个租户创建一个NHibernat

我们正在使用NServiceBus为许多租户执行文档处理

每个租户都有自己的数据库,我们使用NHibernate进行数据访问。在web应用程序中,我们使用IoC工具(StructureMap)来处理会话管理。实际上,我们为每个租户维护一个会话工厂。我们能够从
HttpContext
中识别租户

当我们使用NServiceBus启动文档处理时,我们可以访问租户标识符。我们需要在文档的整个处理过程中都能使用这个租户id(我们有两个传奇故事,并引发了许多事件)

我们需要为每个租户创建一个NHibernate
SessionFactory
,因此在配置StructureMap时需要某种方法来获取租户id

我看到一些帖子建议使用消息头存储租户标识符,但我不确定如何:

  • 首次提交文档时设置消息头(发送
    SubmitDocumentCommand
  • 在配置StructureMap时,请引用标题
  • 访问sagas/handlers中的标题
  • 确保消息头从一条消息流向下一条消息。当我们发送
    SubmitDocumentCommand
    时,它由
    documentsubmitmissionsaga
    处理。如果提交成功,我们将发送
    文档SubmittedEvent
    。我们希望确保租户id在流程中的所有点都可用

  • 我相信,有了这些信息,我可以成功地使用NHibernate实现多租户,但对于这种情况,任何更具体的方法都将不胜感激。

    您可以使用一个注册自身的消息变异器来流式传输头:下面是我自己代码中的一个快速示例。您可以始终使用Bus.CurrentMessageContext.Headers在任何位置设置/访问标题

    希望这有帮助:)

    //
    ///Mutator设置通道头
    /// 
    公共类FlowChannelMutator:IMutateOutgoingTransportMessages,初始化无效
    {
    /// 
    ///需要总线来访问当前消息上下文
    /// 
    公共IBus总线{get;set;}
    /// 
    ///跟踪频道
    /// 
    /// 
    /// 
    public void MutateOutgoing(对象[]消息,传输消息传输消息)
    {
    if(Bus.CurrentMessageContext!=null&&
    Bus.CurrentMessageContext.Headers.ContainsKey(“x-messagehandler-channel”))
    {
    if(!transportMessage.Headers.ContainsKey(“x-messagehandler-channel”))
    {
    transportMessage.Header[“x-messagehandler-channel”]=
    Bus.CurrentMessageContext.Headers[“x-messagehandler-channel”];
    }
    }
    }
    /// 
    ///初始化
    /// 
    公共void Init()
    {
    Configure.Instance.Configurer.ConfigureComponent(DependencyLifecycle.InstancePerCall);
    }
    }
    
    您可以使用一个注册自身的消息变异器来传递标题:下面是我自己代码中的一个快速示例。您可以始终使用Bus.CurrentMessageContext.Headers在任何位置设置/访问标题

    希望这有帮助:)

    //
    ///Mutator设置通道头
    /// 
    公共类FlowChannelMutator:IMutateOutgoingTransportMessages,初始化无效
    {
    /// 
    ///需要总线来访问当前消息上下文
    /// 
    公共IBus总线{get;set;}
    /// 
    ///跟踪频道
    /// 
    /// 
    /// 
    public void MutateOutgoing(对象[]消息,传输消息传输消息)
    {
    if(Bus.CurrentMessageContext!=null&&
    Bus.CurrentMessageContext.Headers.ContainsKey(“x-messagehandler-channel”))
    {
    if(!transportMessage.Headers.ContainsKey(“x-messagehandler-channel”))
    {
    transportMessage.Header[“x-messagehandler-channel”]=
    Bus.CurrentMessageContext.Headers[“x-messagehandler-channel”];
    }
    }
    }
    /// 
    ///初始化
    /// 
    公共void Init()
    {
    Configure.Instance.Configurer.ConfigureComponent(DependencyLifecycle.InstancePerCall);
    }
    }
    
    这帮了大忙。一旦我们有了可用的TenantId,我们就可以配置StructureMap来获得相关的
    SessionFactory
    来处理调用。这非常有帮助。一旦我们有了可用的TenantId,我们就可以配置StructureMap来获取相关的
    SessionFactory
    来处理调用。
    /// <summary>
    /// Mutator to set the channel header
    /// </summary>
    public class FlowChannelMutator : IMutateOutgoingTransportMessages, INeedInitialization
    {
        /// <summary>
        /// The bus is needed to get access to the current message context
        /// </summary>
        public IBus Bus { get; set; }
    
        /// <summary>
        /// Keeps track of the channel
        /// </summary>
        /// <param name="messages"></param>
        /// <param name="transportMessage"></param>
        public void MutateOutgoing(object[] messages, TransportMessage transportMessage)
        {
            if (Bus.CurrentMessageContext != null &&
                Bus.CurrentMessageContext.Headers.ContainsKey("x-messagehandler-channel"))
            {
                if (!transportMessage.Headers.ContainsKey("x-messagehandler-channel"))
                {
                    transportMessage.Headers["x-messagehandler-channel"] =
                        Bus.CurrentMessageContext.Headers["x-messagehandler-channel"];
                }
            }
        }
    
        /// <summary>
        /// Initializes 
        /// </summary>
        public void Init()
        {
            Configure.Instance.Configurer.ConfigureComponent<FlowChannelMutator>(DependencyLifecycle.InstancePerCall);
        }
    }