BOT 框架 - 使用 Cosmos DB 进行状态管理
BOT framework - state management using Cosmos DB
我使用 Cosmos DB 在我的 BOT 框架中启用了日志记录和状态管理,如下所示 link
我也在 Global.ascx 中添加了以下代码
rotected void Application_Start()
{
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
// Bot Storage: register state storage for your bot
var uri = new Uri(ConfigurationManager.AppSettings["DocumentDBUri"]);
var key = ConfigurationManager.AppSettings["DocumentDBKey"];
var store = new DocumentDbBotDataStore(uri, key);
builder.Register(c => store)
.Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
.AsSelf()
.SingleInstance();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
}
Azure 文档数据库:
{
"id": "emulator:private52mgl3acgcke:default-user",
"botId": "lg3443gthi57gd",
"channelId": "emulator",
"conversationId": "52mgl3acgcke",
"userId": "default-user",
"data": {
"ResumptionContext": {
"locale": "en-US",
"isTrustedServiceUrl": false
},
"DialogState": "H4sIAAAAAAAEAO1b22/bVBhPWsdNso6Oq7gMFgQMSlt3SZpeRjeWpOoI62VaOhCqquzYPklNHTv4HHdkjzzBy4TEI4J/ASHxDkICib+CVxB/RPk+20nTNG2c0BQX6ilfk/hcvsvvfN/vnHihcCgU2oML/+I1OgTio1VNsUxmlrmUM+Fla7pKrcnEB9RimmncSEvJlJSSZiYTeVvntkVvGNTmFtEnE3dtWdeUO7S+Ye5QaJmUy+n5zCxR07MzNJ2J4Dw/hjuOLxUMTi2D6Exa1mSYyv3zILm52bn9kkZ0s8Ja+rnfbBC2M5kYmA1bW8NgRIRxouyIZYtUKYs8JBpnw4Lw01CxzjitSnlT16nCYSYm3aYGtTRFWtEYP9qaQ9YXlnHsAJo/0MGJT+8UwaVE1x4R9PFEkZsWLRgQE0OhufpGvUaLtmWZFcLpxLr8MYTiHi1Ti8JtRPjpzIKvGIIlJqCIgBDw4zlKTmIFiiUNfMgiJaY9otHSrjssePpnv/klsL7b3 "
},
"_rid": "JnhaAKnGzgEJAAAAAAAAAA==",
"_self": "dbs/JnhaAA==/colls/JnhaAKnGzgE=/docs/JnhaAKnGzgEJAAAAAAAAAA==/",
"_etag": "\"00002f19-0000-0000-0000-5a56565655000\"",
"_attachments": "attachments/",
"_ts": 1523330900
}
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
var key = new AddressKey()
{
BotId = message.Recipient.Id,
ChannelId = message.ChannelId,
UserId = message.From.Id,
ConversationId = message.Conversation.Id,
ServiceUrl = message.ServiceUrl
};
var userData = await botDataStore.LoadAsync(key, BotStoreType.BotConversationData, CancellationToken.None);
userData.SetProperty("userId", UserID);
userData.SetProperty("DOB", DOB);
BotData botdata = new BotData();
await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
现在,我想为用户添加我所在州的自定义用户数据(Ex、姓名、电子邮件和出生日期),并将其用于完整的对话 -
我找不到任何最好的方法来处理它。
(context.UserData.SetValue - 有效,但我希望它是状态客户端而不是在 cosmos DB 中更新它)
context.UserData.SetValue("username", "John Smith");
不相关,但您实际上可以将代码的 var key
部分更改为 var key = Address.FromActivity(message);
使用下面的代码,我在屏幕截图中得到了结果,其中有一些不同之处,其中之一是我没有使用您代码中的这一行 BotData botdata = new BotData();
并且我还添加了这一行 await botDataStore.FlushAsync(key, CancellationToken.None);
我在 global.asax
中有与你完全相同的代码
if (activity.Type == ActivityTypes.Message)
{
var message = activity as IMessageActivity;
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
var key = Address.FromActivity(message);
ConversationReference r = new ConversationReference();
var userData = await botDataStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);
userData.SetProperty("userId", "123");
userData.SetProperty("DOB", "some date");
await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
await botDataStore.FlushAsync(key, CancellationToken.None);
}
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}
我在我的 cosmosDB 中得到了这个结果
希望对您有所帮助
编辑 2018 年 4 月 12 日
解决您的后续问题。要做到这一点,这段代码已经 运行 你只需要检查键上是否存在该值修改我给你的代码片段,如下所示:
if (userData.GetProperty<string>("userId") == null)
{
userData.SetProperty("userId", "123");
userData.SetProperty("DOB", "some date");
await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
await botDataStore.FlushAsync(key, CancellationToken.None);
}
由于您无权访问上下文对象,其余代码将需要运行让您每次都检查状态。
要回答您关于用户关闭和重新打开 window 的其他问题,它应该保存到您的 cosmosDB 中,这应该不是问题。
我使用 Cosmos DB 在我的 BOT 框架中启用了日志记录和状态管理,如下所示 link
我也在 Global.ascx 中添加了以下代码
rotected void Application_Start()
{
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
// Bot Storage: register state storage for your bot
var uri = new Uri(ConfigurationManager.AppSettings["DocumentDBUri"]);
var key = ConfigurationManager.AppSettings["DocumentDBKey"];
var store = new DocumentDbBotDataStore(uri, key);
builder.Register(c => store)
.Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
.AsSelf()
.SingleInstance();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
}
Azure 文档数据库:
{
"id": "emulator:private52mgl3acgcke:default-user",
"botId": "lg3443gthi57gd",
"channelId": "emulator",
"conversationId": "52mgl3acgcke",
"userId": "default-user",
"data": {
"ResumptionContext": {
"locale": "en-US",
"isTrustedServiceUrl": false
},
"DialogState": "H4sIAAAAAAAEAO1b22/bVBhPWsdNso6Oq7gMFgQMSlt3SZpeRjeWpOoI62VaOhCqquzYPklNHTv4HHdkjzzBy4TEI4J/ASHxDkICib+CVxB/RPk+20nTNG2c0BQX6ilfk/hcvsvvfN/vnHihcCgU2oML/+I1OgTio1VNsUxmlrmUM+Fla7pKrcnEB9RimmncSEvJlJSSZiYTeVvntkVvGNTmFtEnE3dtWdeUO7S+Ye5QaJmUy+n5zCxR07MzNJ2J4Dw/hjuOLxUMTi2D6Exa1mSYyv3zILm52bn9kkZ0s8Ja+rnfbBC2M5kYmA1bW8NgRIRxouyIZYtUKYs8JBpnw4Lw01CxzjitSnlT16nCYSYm3aYGtTRFWtEYP9qaQ9YXlnHsAJo/0MGJT+8UwaVE1x4R9PFEkZsWLRgQE0OhufpGvUaLtmWZFcLpxLr8MYTiHi1Ti8JtRPjpzIKvGIIlJqCIgBDw4zlKTmIFiiUNfMgiJaY9otHSrjssePpnv/klsL7b3 "
},
"_rid": "JnhaAKnGzgEJAAAAAAAAAA==",
"_self": "dbs/JnhaAA==/colls/JnhaAKnGzgE=/docs/JnhaAKnGzgEJAAAAAAAAAA==/",
"_etag": "\"00002f19-0000-0000-0000-5a56565655000\"",
"_attachments": "attachments/",
"_ts": 1523330900
}
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
var key = new AddressKey()
{
BotId = message.Recipient.Id,
ChannelId = message.ChannelId,
UserId = message.From.Id,
ConversationId = message.Conversation.Id,
ServiceUrl = message.ServiceUrl
};
var userData = await botDataStore.LoadAsync(key, BotStoreType.BotConversationData, CancellationToken.None);
userData.SetProperty("userId", UserID);
userData.SetProperty("DOB", DOB);
BotData botdata = new BotData();
await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
现在,我想为用户添加我所在州的自定义用户数据(Ex、姓名、电子邮件和出生日期),并将其用于完整的对话 - 我找不到任何最好的方法来处理它。
(context.UserData.SetValue - 有效,但我希望它是状态客户端而不是在 cosmos DB 中更新它)
context.UserData.SetValue("username", "John Smith");
不相关,但您实际上可以将代码的 var key
部分更改为 var key = Address.FromActivity(message);
使用下面的代码,我在屏幕截图中得到了结果,其中有一些不同之处,其中之一是我没有使用您代码中的这一行 BotData botdata = new BotData();
并且我还添加了这一行 await botDataStore.FlushAsync(key, CancellationToken.None);
我在 global.asax
if (activity.Type == ActivityTypes.Message)
{
var message = activity as IMessageActivity;
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
var key = Address.FromActivity(message);
ConversationReference r = new ConversationReference();
var userData = await botDataStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);
userData.SetProperty("userId", "123");
userData.SetProperty("DOB", "some date");
await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
await botDataStore.FlushAsync(key, CancellationToken.None);
}
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}
我在我的 cosmosDB 中得到了这个结果
希望对您有所帮助
编辑 2018 年 4 月 12 日
解决您的后续问题。要做到这一点,这段代码已经 运行 你只需要检查键上是否存在该值修改我给你的代码片段,如下所示:
if (userData.GetProperty<string>("userId") == null)
{
userData.SetProperty("userId", "123");
userData.SetProperty("DOB", "some date");
await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
await botDataStore.FlushAsync(key, CancellationToken.None);
}
由于您无权访问上下文对象,其余代码将需要运行让您每次都检查状态。
要回答您关于用户关闭和重新打开 window 的其他问题,它应该保存到您的 cosmosDB 中,这应该不是问题。