【问题标题】:Multi-tenant bot data store多租户机器人数据存储
【发布时间】:2018-08-26 02:05:04
【问题描述】:

我一直在为 C# 中的多租户 azure bot 实现以下功能,这对于验证应用凭据非常有用。

C# : Creating a Single Bot Service to Support Multiple Bot Applications

https://www.microsoft.com/developerblog/2017/01/10/creating-a-single-bot-service-to-support-multiple-bot-applications/

但是,我想知道机器人数据存储是否也可以这样做? 我目前有标准的 Azure 表存储机器人数据存储,它使用 web.config 中定义的单个连接字符串:

Conversation.UpdateContainer(
            builder =>
            {
                builder.RegisterModule(new ReflectionSurrogateModule());

                builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));

                //var store = new InMemoryDataStore();

                var store = new TableBotDataStore(ConfigurationManager.AppSettings["BotStorage"]);

                builder.Register(c => store)
                    .Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
                    .AsSelf()
                    .SingleInstance();
            });

在我的 ICredentialProvider 实现中(如文章示例中所述)。如果我将客户连接字符串与他们的 App ID 和密码一起存储,是否可以根据客户/机器人序列化数据存储在上面的依赖注入中提取该引用,然后将该数据保存/读取到客户 Azure 表存储?

【问题讨论】:

  • If I store the customers connection string along side their App ID and Password, is it possible to pull that reference in the dependency injection above based on the customer/bot serialising the data store and then save/read that data to the customers Azure table storage? 您能否详细说明您的要求?是否要将带有 Microsoft appId 和密码的存储连接字符串存储到字典中,并在注册 TableBotDataStore 时访问存储连接字符串?
  • @FeiHan 差不多。它们不必全部存储在一起,但我认为将 azure 连接字符串与应用程序 ID 一起存储是最合乎逻辑的地方。我的想法是,我可以根据 Http 上下文身份声明拉取连接字符串(类似于通过多重身份验证实现的)

标签: c# botframework multi-tenant azure-table-storage


【解决方案1】:

您需要创建一个实现IBotDataStore&lt;BotData&gt; 的自定义机器人数据存储并使用它。我能够得到一个简单的,每次都创建相同的TableBotDataStore。下面是我使用的,每次发送消息时都会触发构造函数中的断点。

public class CustomBotStore : IBotDataStore<BotData>
{
    private IBotDataStore<BotData> _store;

    public CustomBotStore()
    {
        string connString = ConfigurationManager.ConnectionStrings["BotState"].ConnectionString;

        _store = new TableBotDataStore(connString, "testbotdata"); // requires Microsoft.BotBuilder.Azure Nuget package 
    }

    public Task<bool> FlushAsync(IAddress key, CancellationToken cancellationToken)
    {
        return _store.FlushAsync(key, cancellationToken);
    }

    public Task<BotData> LoadAsync(IAddress key, BotStoreType botStoreType, CancellationToken cancellationToken)
    {
        return _store.LoadAsync(key, botStoreType, cancellationToken);
    }

    public Task SaveAsync(IAddress key, BotStoreType botStoreType, BotData data, CancellationToken cancellationToken)
    {
        return _store.SaveAsync(key, botStoreType, data, cancellationToken);
    }
}


public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);

        Conversation.UpdateContainer(
        builder =>
        {
            builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));

            builder.Register(c => new CustomBotStore())
                .Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
                .AsSelf()
                .InstancePerLifetimeScope();
        });
    }
}

我不确定每个生命周期范围内都有一个实例的含义是什么,因为该示例使用单个实例。但是您应该可以使用它,然后检查构造函数中的HttpContext 并使用正确的连接字符串。

【讨论】:

  • 我最终通过在 autofac 寄存器 lambda 表达式中调用新的 TableBotDataStore 并使用用户声明身份上的 GetAppIDFromClaims() 扩展方法从字典中提取连接字符串来进一步简化此操作。跨度>
  • 您在哪里添加了您的 autofac 寄存器 lambda 表达式?您是否在 Application_Start() 方法中迭代了所有租户来做到这一点?您如何解决管理多个 TableBotDataStore 实例(每个租户一个)的问题?
猜你喜欢
  • 1970-01-01
  • 2016-11-25
  • 2015-03-06
  • 1970-01-01
  • 2014-03-21
  • 1970-01-01
  • 2013-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多