如何在Azure Cosmos DB(BotFramework)中存储UserState和ConversationState? [英] How to store UserState and ConversationState in Azure Cosmos DB (BotFramework)?

查看:128
本文介绍了如何在Azure Cosmos DB(BotFramework)中存储UserState和ConversationState?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用De Bot Framework V4版本的机器人.该文档真的很糟糕,当我尝试存储de UserSate和ConversationState时,我遇到了Cosmos DB(Azure)的问题.

I'm doing a bot with de Microsoft Bot Framework version V4. The documentation is really awful, and I'm having problems with Cosmos DB (Azure) when I try to store de UserSate and the ConversationState.

我尝试了Google的所有结果,但没有任何效果.另外,实际上没有太多有关该框架的信息.

I tried every result in Google but nothing has worked yet. Plus, there no much information about the framework really.

下面是文件Startup.cs的代码.

Bellow is the code of the file Startup.cs.

public void ConfigureServices(IServiceCollection services)
{
    services.AddBot<SeguritoBot>(options =>
   {
       var secretKey = Configuration.GetSection("botFileSecret")?.Value;
       var botFilePath = Configuration.GetSection("botFilePath")?.Value;

    // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
    var botConfig = BotConfiguration.Load(botFilePath ?? @".\Segurito.bot", secretKey);
   services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded. ({botConfig})"));

    // Retrieve current endpoint.
    var environment = _isProduction ? "production" : "development";
   var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment);
   if (!(service is EndpointService endpointService))
   {
       throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
   }

   options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);

    // Creates a logger for the application to use.
    ILogger logger = _loggerFactory.CreateLogger<SeguritoBot>();

    // Catches any errors that occur during a conversation turn and logs them.
    options.OnTurnError = async (context, exception) =>
   {
       logger.LogError($"Exception caught : {exception}");
       await context.SendActivityAsync("Sorry, it looks like something went wrong.");
   };

   var optionsConversation = new CosmosDbStorageOptions()
   {
       CosmosDBEndpoint = new Uri("--secret--"),
       AuthKey = "--secret--",
       DatabaseId = "--secret--",
       CollectionId = "--secret--"
   };

   var optionsUser = new CosmosDbStorageOptions()
   {
       CosmosDBEndpoint = new Uri("--secret--"),
       AuthKey = "--secret--",
       DatabaseId = "--secret--",
       CollectionId = "--secret--"
   };

   IStorage dataStoreConversationState = new CosmosDbStorage(optionsConversation);
   IStorage dataStoreUserState = new CosmosDbStorage(optionsUser);

   options.Middleware.Add(new ConversationState<ConversationState>(dataStoreConversationState));
   options.Middleware.Add(new UserState<UserState>(dataStoreUserState));
   });
}

最后一行显示错误:

The non-generic type 'ConversationState' cannot be used with type arguments
The non-generic type 'ConversationState' cannot be used with type arguments 

推荐答案

好吧,我不确定您从何处获得此代码,但看起来好像来自预发行版本. ConversationStateUserState不再是中间件,也不再是通用的(例如,没有类型参数).

Ok, I'm not sure where you got this code from, but it looks like it's from a pre-release build. ConversationState and UserState are no longer middleware and no longer generic (e.g. don't have type arguments).

当使用CosmosDB在4.x发行版上进行状态存储时,这是Startup::ConfigureServices的外观:

This is what a Startup::ConfigureServices should look like when using CosmosDB for state storage on a 4.x release build:

public class Startup
{
     public void ConfigureServices(IServiceCollection services)
     {
        // Only need a single storage instance unless you really are storing your conversation state and user state in two completely DB instances
        var storage = new CosmosDbStorage(new CosmosDbStorageOptions
        {
            // … set options here …
        });

        var conversationState = new ConversationState(storage);
        var userState = new UserState(storage);

        // Add the states as singletons
        services.AddSingleton(conversationState);
        services.AddSingleton(userState);

        // Create state properties accessors and register them as singletons
        services.AddSingleton(conversationState.CreateProperty<YourBotConversationState>("MyBotConversationState"));
        services.AddSingleton(userState.CreateProperty<YourBotUserState>("MyBotUserState"));

        services.AddBot<SeguritoBot>(options =>
        {
           // … set options here …
        });
     }
}

现在,在您的机器人中,如果要访问这些属性,可以通过构造函数将它们作为依赖项:

Now, in your bot, if you want to access those properties, you take them as dependencies via the constructor:

public class SeguritoBot : IBot
{
    private readonly ConversationState _conversationState;
    private readonly UserState _userState;
    private readonly IStatePropertyAccessor<YourBotConversationState> _conversationStatePropertyAccessor;
    private readonly IStatePropertyAccessor<YourBotUserState> _userStatePropertyAccessor;

    public SeguritoBot(
        ConversationState conversationState, 
        UserState userState,
        IStatePropertyAccessor<YourBotConversationState> conversationStatePropertyAccessor,
        IStatePropertyAccessor<YourBotUserState> userStatePropertyAccesssor)
    {
        _conversationState = conversationState;
        _userState = userState;
        _conversationStatePropertyAcessor = conversationStatePropertyAcessor;
        _userStatePropertyAcessor = userStatePropertyAcessor;
    }

    public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        var currentConversationState = await _conversationStatePropertyAccessor.GetAsync(
            turnContext,
            () => new YourBotConversationState(), 
            cancellationToken);

        // Access properties for this conversation
        // currentConversationState.SomeProperty

        // Update your conversation state property
        await _conversationStatePropertyAccessor.SetAsync(turnContext, currentConversationState, cancellationToken);

        // Commit any/all changes to conversation state properties
        await _conversationState.SaveChangesAsync(turnContext, cancellationToken);
    }
}

显然,您可以对用户状态属性执行相同的操作,并且可以通过对CreateProperty的更多调用以及对这些IStatePropertyAccessor<T>的注入等,在每个状态范围内支持多个属性.

Obviously you can do the same with the user state property and you can support multiple properties per state scope with more calls to CreateProperty and injecting those IStatePropertyAccessor<T> as well, etc.

这篇关于如何在Azure Cosmos DB(BotFramework)中存储UserState和ConversationState?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆