Microsoft Bot Framework:异常:数据已更改
Microsoft Bot Framework: Exception: The data is changed
我有一个具有以下对话场景的机器人:
- 向 LUIS 发送文本
- LUIS 意图调用
context.Call(...)
以启动对话
此对话框终止,在用户数据中保存一些信息:
private static async Task storeBotData(IDialogContext context, BotData userData)
{
Activity activity = (Activity)context.Activity;
StateClient sc = activity.GetStateClient();
await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData);
}
在调用另一个对话框后,再次使用 context.Call(...)
。
然后最后一个对话框运行并终止。
我的问题是,在第一个对话结束时(第 3 步)更新用户数据时,Bot Framework Channel Emulator 出现以下异常:
`Exception: The data is changed [File of type 'text/plain']`...
这里发生了什么?我认为当对话框终止时,它会自己调用 setUserData
,但我不明白为什么我不能在代码中的任何地方更新 userData...
我试图捕获异常,但没有捕获到任何异常。但是我知道 userData 已更新,因为当我尝试取回它时,它已更新...
欢迎任何帮助:)
谢谢
Botframework
restores/saves 每次 activity 动作后的对话状态,所以在幕后典型的流程如下所示:
[23:15:40] <- GET 200 getUserData
[23:15:47] <- GET 200 getConversationData
[23:15:47] <- GET 200 getPrivateConversationData
...
[23:16:42] <- POST 200 setConversationData
[23:16:42] <- POST 200 setUserData
[23:16:42] <- POST 200 setPrivateConversationData
正如所提到的 here : These botData objects will fail to be stored if another instance of your bot has changed the object already.
所以在你的情况下,异常发生在对话框结束时,当框架自己调用 setUserData 并发现 BotData 已经被更改时(通过您明确调用 BotState.SetUserDataAsync
)。我想这就是您无法捕获异常的原因。
解法:
我使用了以下代码并解决了问题:
private static void storeBotData(IDialogContext context, BotData userData)
{
var data = context.UserData;
data.SetValue("field_name", false);
}
它起作用的原因是我们修改了 UserData 的对象,但允许 botFramework 自己"commit"它,所以没有冲突
我同意@Artem(这也解决了我的问题,谢谢!)。我只想添加以下准则。
使用
var data = context.UserData;
data.SetValue("field_name", false);
只要有可用的 IDialogContext 对象,就让 Bot Framework 提交更改。
改用
StateClient sc = activity.GetStateClient();
await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData);
当您没有 IDialogContext 对象时,例如在 MessageController class.
我有一个具有以下对话场景的机器人:
- 向 LUIS 发送文本
- LUIS 意图调用
context.Call(...)
以启动对话 此对话框终止,在用户数据中保存一些信息:
private static async Task storeBotData(IDialogContext context, BotData userData) { Activity activity = (Activity)context.Activity; StateClient sc = activity.GetStateClient(); await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData); }
在调用另一个对话框后,再次使用
context.Call(...)
。然后最后一个对话框运行并终止。
我的问题是,在第一个对话结束时(第 3 步)更新用户数据时,Bot Framework Channel Emulator 出现以下异常:
`Exception: The data is changed [File of type 'text/plain']`...
这里发生了什么?我认为当对话框终止时,它会自己调用 setUserData
,但我不明白为什么我不能在代码中的任何地方更新 userData...
我试图捕获异常,但没有捕获到任何异常。但是我知道 userData 已更新,因为当我尝试取回它时,它已更新...
欢迎任何帮助:)
谢谢
Botframework
restores/saves 每次 activity 动作后的对话状态,所以在幕后典型的流程如下所示:
[23:15:40] <- GET 200 getUserData
[23:15:47] <- GET 200 getConversationData
[23:15:47] <- GET 200 getPrivateConversationData
...
[23:16:42] <- POST 200 setConversationData
[23:16:42] <- POST 200 setUserData
[23:16:42] <- POST 200 setPrivateConversationData
正如所提到的 here : These botData objects will fail to be stored if another instance of your bot has changed the object already.
所以在你的情况下,异常发生在对话框结束时,当框架自己调用 setUserData 并发现 BotData 已经被更改时(通过您明确调用 BotState.SetUserDataAsync
)。我想这就是您无法捕获异常的原因。
解法: 我使用了以下代码并解决了问题:
private static void storeBotData(IDialogContext context, BotData userData)
{
var data = context.UserData;
data.SetValue("field_name", false);
}
它起作用的原因是我们修改了 UserData 的对象,但允许 botFramework 自己"commit"它,所以没有冲突
我同意@Artem(这也解决了我的问题,谢谢!)。我只想添加以下准则。
使用
var data = context.UserData;
data.SetValue("field_name", false);
只要有可用的 IDialogContext 对象,就让 Bot Framework 提交更改。
改用
StateClient sc = activity.GetStateClient();
await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData);
当您没有 IDialogContext 对象时,例如在 MessageController class.