N服务总线、NHibernate和多租户
我们正在使用NServiceBus为许多租户执行文档处理 每个租户都有自己的数据库,我们使用NHibernate进行数据访问。在web应用程序中,我们使用IoC工具(StructureMap)来处理会话管理。实际上,我们为每个租户维护一个会话工厂。我们能够从N服务总线、NHibernate和多租户,nhibernate,structure,nservicebus,multi-tenant,Nhibernate,Structure,Nservicebus,Multi Tenant,我们正在使用NServiceBus为许多租户执行文档处理 每个租户都有自己的数据库,我们使用NHibernate进行数据访问。在web应用程序中,我们使用IoC工具(StructureMap)来处理会话管理。实际上,我们为每个租户维护一个会话工厂。我们能够从HttpContext中识别租户 当我们使用NServiceBus启动文档处理时,我们可以访问租户标识符。我们需要在文档的整个处理过程中都能使用这个租户id(我们有两个传奇故事,并引发了许多事件) 我们需要为每个租户创建一个NHibernat
HttpContext
中识别租户
当我们使用NServiceBus启动文档处理时,我们可以访问租户标识符。我们需要在文档的整个处理过程中都能使用这个租户id(我们有两个传奇故事,并引发了许多事件)
我们需要为每个租户创建一个NHibernateSessionFactory
,因此在配置StructureMap时需要某种方法来获取租户id
我看到一些帖子建议使用消息头存储租户标识符,但我不确定如何:
SubmitDocumentCommand
)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);
}
}