Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义IBotDataStore中断context.PrivateConversationData_C#_Azure_Botframework - Fatal编程技术网

C# 自定义IBotDataStore中断context.PrivateConversationData

C# 自定义IBotDataStore中断context.PrivateConversationData,c#,azure,botframework,C#,Azure,Botframework,我使用的是Bot Builder 3.8.5 如Microsoft Bot Framework文档中所述: 默认情况下,.NET的Bot Framework SDK使用 Bot框架状态服务,仅用于原型设计 并且不是为机器人程序在生产环境中使用而设计的。对于 由于生产环境中的性能和安全原因 应该使用Bot Builder SDK Azure扩展来存储状态 您自己的Azure表存储或Azure DocumentDB存储中的数据,或 创建IBotDataStore的自定义实现,以在中存储状态数据 指定

我使用的是Bot Builder 3.8.5

如Microsoft Bot Framework文档中所述:

默认情况下,.NET的Bot Framework SDK使用 Bot框架状态服务,仅用于原型设计 并且不是为机器人程序在生产环境中使用而设计的。对于 由于生产环境中的性能和安全原因 应该使用Bot Builder SDK Azure扩展来存储状态 您自己的Azure表存储或Azure DocumentDB存储中的数据,或 创建IBotDataStore的自定义实现,以在中存储状态数据 指定的目的地

我决定在Azure表存储中使用Bot builder扩展。状态已正确保存到表存储器中

但是,我有以下问题:

MessageController.cs
中,我正在添加一个私人对话数据字符串,如下所示(因为我无权访问
IDialogContext
):

但是context.PrivateConversationData不包含此键,它始终返回null

注意:当我使用默认的Bot状态服务时,它工作得非常好

如果我使用以下代码,它可以工作,但对性能有很大影响(检索botdata的调用非常慢):

var stateClient=context.Activity.GetStateClient();
BotData pConversationData=context.Activity.GetStateClient().BotState.GetPrivateConversationDataAsync(context.Activity.ChannelId,context.Activity.Conversation.Id,context.Activity.From.Id)。GetWaiter().GetResult();
返回pConversationData.GetProperty(“MyKey”);
我做错了什么

更新


似乎覆盖IBotDataStore(使用bot builder扩展)对context.UserData有效,但对StateClient.BotState无效。。。事实上,我认为我也需要有一个IBotState的自定义实现,以便在IDialog之外访问BotState。

在此处设置用户数据值时:

StateClient stateClient = activity.GetStateClient();
BotData userData = await stateClient.BotState.GetPrivateConversationDataAsync(activity.ChannelId, activity.Conversation.Id, activity.From.Id);
userData.SetProperty<string>("MyKey", "MyValue"); 

然后,在此处设置用户数据值时,应正确存储和访问该值

StateClient stateClient = activity.GetStateClient();
BotData userData = await stateClient.BotState.GetPrivateConversationDataAsync(activity.ChannelId, activity.Conversation.Id, activity.From.Id);
userData.SetProperty<string>("MyKey", "MyValue"); 

然后它应该被正确地存储和访问

我想我找到了解决这个问题的方法。问题在于,如果您希望在IDialog之外访问Bot状态,则无法访问IDialogContext和context.PrivateConversationData或context.UserData,因为它们正在处理Bot状态的加载/保存/刷新

如果您正在使用默认的bot状态服务,则可以使用StateClient,但如果您有自定义的IBotDataStore(如bot框架文档中所建议的),则不能使用默认的StateClient,因为它仍然指向默认的状态服务。我想一个解决方案是创建一个定制的IStateClient/IBotState

相反,我在MessageController中使用了以下代码:

using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
        var botData = scope.Resolve<IBotData>();
        await botData.LoadAsync(default(CancellationToken));
        botData.PrivateConversationData.SetValue<T>("MyKey", value);
        await botData.FlushAsync(default(CancellationToken));
}
使用(var scope=DialogModule.BeginLifetimeScope(Conversation.Container,activity))
{
var botData=scope.Resolve();
等待botData.LoadAsync(默认值(CancellationToken));
botData.PrivateConversationData.SetValue(“MyKey”,值);
等待botData.FlushAsync(默认值(CancellationToken));
}
有了这段代码,我就能够在自定义IBotDataStore中保存/加载数据


希望这有帮助

我想我找到了克服这个问题的方法。问题在于,如果您希望在IDialog之外访问Bot状态,则无法访问IDialogContext和context.PrivateConversationData或context.UserData,因为它们正在处理Bot状态的加载/保存/刷新

如果您正在使用默认的bot状态服务,则可以使用StateClient,但如果您有自定义的IBotDataStore(如bot框架文档中所建议的),则不能使用默认的StateClient,因为它仍然指向默认的状态服务。我想一个解决方案是创建一个定制的IStateClient/IBotState

相反,我在MessageController中使用了以下代码:

using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
        var botData = scope.Resolve<IBotData>();
        await botData.LoadAsync(default(CancellationToken));
        botData.PrivateConversationData.SetValue<T>("MyKey", value);
        await botData.FlushAsync(default(CancellationToken));
}
使用(var scope=DialogModule.BeginLifetimeScope(Conversation.Container,activity))
{
var botData=scope.Resolve();
等待botData.LoadAsync(默认值(CancellationToken));
botData.PrivateConversationData.SetValue(“MyKey”,值);
等待botData.FlushAsync(默认值(CancellationToken));
}
有了这段代码,我就能够在自定义IBotDataStore中保存/加载数据


希望这有帮助

抱歉,我忘了在原始问题中添加这行代码。但不幸的是,我已经在做了。。。它仍然可以使用默认的bot状态服务,但不能使用自定义表数据存储。(在原来的问题上加上一行)可能是延迟问题还是其他问题?你能在几秒钟后得到这个值吗?你能看看你的存储并检查一下什么时候增值吗?我只是想等一下,但什么都没有。。。这很奇怪。。它与默认的bot状态服务配合得很好。。这两种检索/设置上下文的方法是否完全相同?从调试的角度来看,我首先要检查我的值是否真的存储了;)如果我使用以下代码行:var stateClient=context.Activity.GetStateClient();BotData pConversationData=context.Activity.GetStateClient().BotState.GetPrivateConversationDataAsync(context.Activity.ChannelId,context.Activity.Conversation.Id,context.Activity.From.Id)。GetWaiter().GetResult();返回pConversationData.GetProperty(“MyKey”);我设法获得了我的密钥的值(即使我还没有在表存储中看到它),所以我猜有一个缓存机制。但是对于context.PrivateConversationData,什么都没有..抱歉,我忘了在原始问题中添加这行代码。但不幸的是,我已经在做了。。。它仍然可以使用默认的bot状态服务,但不能使用自定义表数据存储。(在原来的问题上加上一行)也许是一个de
await stateClient.BotState.SetPrivateConversationDataAsync(activity.ChannelId, activity.Conversation.Id, activity.From.Id, userData);
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
        var botData = scope.Resolve<IBotData>();
        await botData.LoadAsync(default(CancellationToken));
        botData.PrivateConversationData.SetValue<T>("MyKey", value);
        await botData.FlushAsync(default(CancellationToken));
}