Gravar diretamente no armazenamento
APLICA-SE A: SDK v4
Você pode ler e gravar diretamente em seu objeto de armazenamento sem usar middleware ou objeto de contexto. Isso pode ser apropriado para dados que seu bot usa para preservar a conversa ou dados originados de uma fonte fora do fluxo de conversa do bot. Nesse modelo de armazenamento de dados, os dados são lidos diretamente do armazenamento em vez de usar um gerenciador de estado. Os exemplos de código neste artigo mostram como ler e gravar dados no armazenamento usando os armazenamentos de memória, Cosmos DB, Blob do Azure e transcrição do Blob do Azure.
Observação
Os SDKs JavaScript, C# e Python do Bot Framework continuarão a ser compatíveis. No entanto, o SDK Java está sendo desativado, com o suporte final de longo prazo terminando em novembro de 2023.
Os bots existentes criados com o SDK para Java continuarão a funcionar.
Para a criação de novos bots, considere usar o Microsoft Copilot Studio e leia sobre como escolher a solução de copiloto certa.
Para obter mais informações, confira O futuro da criação de bots.
Pré-requisitos
- Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.
- Familiaridade com a criação de um bot localmente.
- Modelos do SDK do Bot Framework v4 para Visual Studio (C#), Node.js ou Yeoman.
Observação
Você pode instalar os modelos de dentro do Visual Studio.
- No menu, selecione Extensões e Gerenciar extensões.
- Na caixa de diálogo Gerenciar extensões, localize e instale os modelos de SDK do Bot Framework v4 para o Visual Studio.
Para obter informações sobre a implantação de bots .NET no Azure, confira como Provisionar e publicar um bot.
Sobre este exemplo
O código de exemplo neste artigo começa com a estrutura de um bot de eco básico e estende a funcionalidade dele, adicionando códigos (fornecidos abaixo). Esse código estendido cria uma lista para preservar as entradas de usuário conforme elas são recebidas. A cada turno, a lista completa de entradas de usuário salvas na memória é ecoada de volta para o usuário. A estrutura de dados que contém essa lista de entradas é então modificada para ser salva no armazenamento. Vários tipos de armazenamento são explorados à medida que outras funcionalidades são adicionadas a esse código de exemplo.
Importante
Este artigo contém exemplos de código herdados usando cadeias de conexão em arquivos de configuração para conexão interna com o armazenamento. A Microsoft recomenda que você use o fluxo de autenticação mais seguro disponível. Se você estiver se conectando a um recurso do Azure, Identidades Gerenciadas para recursos do Azure será o método de autenticação recomendado.
Armazenamento de memória
O SDK do Bot Framework permite que você armazene entradas do usuário usando o armazenamento na memória. Como o armazenamento na memória é limpo sempre que o bot é reiniciado, ele é mais adequado para fins de teste e não se destina ao uso em produção. Os tipos de armazenamento persistentes, como o armazenamento de banco de dados, são melhores para bots de produção.
Crie um bot básico
O restante deste tópico se baseia em um bot de Eco. O código de exemplo do bot Echo pode ser criado localmente seguindo as instruções de início rápido para Criar um bot.
Substitua o código em EchoBot.cs pelo seguinte código:
using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
// Represents a bot saves and echoes back user input.
public class EchoBot : ActivityHandler
{
// Create local Memory Storage.
private static readonly MemoryStorage _myStorage = new MemoryStorage();
// Create cancellation token (used by Async Write operation).
public CancellationToken cancellationToken { get; private set; }
// Class for storing a log of utterances (text of messages) as a list.
public class UtteranceLog : IStoreItem
{
// A list of things that users have said to the bot
public List<string> UtteranceList { get; } = new List<string>();
// The number of conversational turns that have occurred
public int TurnNumber { get; set; } = 0;
// Create concurrency control where this is used.
public string ETag { get; set; } = "*";
}
// Echo back user input.
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
// preserve user input.
var utterance = turnContext.Activity.Text;
// Make empty local log-items list.
UtteranceLog logItems = null;
// See if there are previous messages saved in storage.
try
{
string[] utteranceList = { "UtteranceLog" };
logItems = _myStorage.ReadAsync<UtteranceLog>(utteranceList).Result?.FirstOrDefault().Value;
}
catch
{
// Inform the user an error occurred.
await turnContext.SendActivityAsync("Sorry, something went wrong reading your stored messages!");
}
// If no stored messages were found, create and store a new entry.
if (logItems is null)
{
// Add the current utterance to a new object.
logItems = new UtteranceLog();
logItems.UtteranceList.Add(utterance);
// Set initial turn counter to 1.
logItems.TurnNumber++;
// Show user new user message.
await turnContext.SendActivityAsync($"{logItems.TurnNumber}: The list is now: {string.Join(", ", logItems.UtteranceList)}");
// Create dictionary object to hold received user messages.
var changes = new Dictionary<string, object>();
{
changes.Add("UtteranceLog", logItems);
}
try
{
// Save the user message to your Storage.
await _myStorage.WriteAsync(changes, cancellationToken);
}
catch
{
// Inform the user an error occurred.
await turnContext.SendActivityAsync("Sorry, something went wrong storing your message!");
}
}
// Else, our storage already contained saved user messages, add new one to the list.
else
{
// add new message to list of messages to display.
logItems.UtteranceList.Add(utterance);
// increment turn counter.
logItems.TurnNumber++;
// show user new list of saved messages.
await turnContext.SendActivityAsync($"{logItems.TurnNumber}: The list is now: {string.Join(", ", logItems.UtteranceList)}");
// Create Dictionary object to hold new list of messages.
var changes = new Dictionary<string, object>();
{
changes.Add("UtteranceLog", logItems);
};
try
{
// Save new list to your Storage.
await _myStorage.WriteAsync(changes,cancellationToken);
}
catch
{
// Inform the user an error occurred.
await turnContext.SendActivityAsync("Sorry, something went wrong storing your message!");
}
}
}
}
Inicie seu bot
Execute o bot localmente.
Iniciar o emulador e conectar seu bot
Instale o Bot Framework Emulator, depois inicie o Emulator e conecte-se ao bot no Emulator:
- Selecione o link Criar nova configuração de bot na guia Boas-vindas do Emulator.
- Preencha os campos para se conectar ao seu bot considerando as informações na página da Web exibida ao iniciar o bot.
Interagir com o bot
Envie uma mensagem ao bot. Ele listará as mensagens recebidas.
O restante deste artigo demonstrará como salvar no armazenamento persistente em vez de na memória interna do bot.
Usar o Cosmos DB
Importante
A classe de armazenamento do Cosmos DB foi preterida. Os contêineres criados originalmente com o CosmosDbStorage não tinham nenhuma chave de partição definida e receberam a chave de partição padrão de _/partitionKey.
Os contêineres criados com o armazenamento do Cosmos DB podem ser usados com o armazenamento particionado do Cosmos DB. Para obter mais informações, leia Particionamento no Azure Cosmos DB.
Observe também que, ao contrário do armazenamento herdado do Cosmos DB, o armazenamento particionado do Cosmos DB não cria automaticamente um banco de dados dentro da sua conta do Cosmos DB. Você precisa criar um novo banco de dados manualmente, mas ignore a criação manual de um contêiner, pois o CosmosDbPartitionedStorage criará o contêiner para você.
Agora que você usou o armazenamento de memória, vamos atualizar o código para usar o Azure Cosmos DB. O Cosmos DB é o banco de dados multimodelo globalmente distribuído da Microsoft. O Azure Cosmos DB permite que você dimensione a taxa de transferência e o armazenamento de maneira elástica e independente em qualquer número de regiões geográficas do Azure. Ele oferece garantias de taxa de transferência, disponibilidade, latência e consistência com contratos de nível de serviço (SLAs) abrangentes.
Configurar um recurso do Cosmos DB
Para usar o Cosmos DB em seu bot, você precisará criar um recurso de banco de dados antes de mexer no código. Para obter uma descrição detalhada do banco de dados e da criação de aplicativos do Cosmos DB, confira o guia de início rápido para .NET, Node.js ou Python.
Criar sua conta de banco de dados
Vá para o portal do Azure para criar uma conta do Azure Cosmos DB. Pesquise e selecione Azure Cosmos DB.
Na página Azure Cosmos DB, escolha Novo para abrir a página Criar Conta do Azure Cosmos DB.
Forneça valores para os seguintes campos:
- Assinatura. Selecione a assinatura do Azure que você deseja usar para essa conta do Azure Cosmos.
- Grupo de recursos. Escolha um grupo de recursos existente ou escolha Criar novo e insira um nome para o grupo de recursos novo.
- Nome da conta. Insira um nome para identificar a conta do Azure Cosmos. Já que documents.Azure.com é acrescentado ao nome que você fornece para criar o URI, use um nome exclusivo. Observe as diretrizes abaixo:
- O nome deve ser exclusivo em todo o Azure.
- O nome deve ter entre 3 e 31 caracteres.
- Apenas letras minúsculas, números e o caractere de hífen (-) podem ser incluídas no nome.
- API. Selecione Core (SQL)
- Local. Selecione um local mais próximo dos usuários para fornecer a eles acesso mais rápido aos dados.
Selecione Examinar + criar.
Após a validação, selecione Criar.
A criação da conta leva alguns minutos. Aguarde até que o portal exiba a página Parabéns! Sua conta do Azure Cosmos DB foi criada.
Adicionar um banco de dados
Observação
Não crie o contêiner sozinho. O bot vai criá-lo para você ao criar seu respectivo cliente interno do Cosmos DB. Isso garante que ele esteja configurado corretamente para armazenar o estado do bot.
Navegue até a página Data Explorer em sua conta do Cosmos DB recém-criada e, em seguida, escolha Novo Banco de Dados na caixa suspensa do Novo Contêiner. Um painel será aberto no lado direito da janela, no qual você poderá inserir os detalhes do novo banco de dados.
Insira uma ID para o novo banco de dados e, opcionalmente, defina a produtividade (você poderá alterar isso mais tarde) e, por fim, escolha OK para criar seu banco de dados. Ao configurar seu bot, anote essa ID de banco de dados para uso posterior.
Agora que criou uma conta do Cosmos DB e um banco de dados, você precisa copiar alguns dos valores para integrar seu novo banco de dados ao bot. Para recuperá-los, navegue até a guia Chaves na seção de configurações do banco de dados da sua conta do Cosmos DB. Dessa página, você precisará do URI (ponto de extremidade do Cosmos DB) e da CHAVE PRIMÁRIA (chave de autorização).
Agora você deve ter uma conta do Cosmos DB com um banco de dados e os seguintes valores prontos para usar nas configurações de bot.
- URI
- Chave Primária
- ID do banco de dados
Adicionar informações de configuração do Cosmos DB
Use os detalhes que você anotou na parte anterior deste artigo para definir o ponto de extremidade, a chave de autorização e a ID do banco de dados. Por fim, você precisa escolher um nome apropriado para o contêiner que será criado no banco de dados para armazenar o estado do bot. No exemplo abaixo, o contêiner do Cosmos DB criado será chamado de "bot-storage".
Adicione as informações a seguir ao arquivo de configuração.
appsettings.json
"CosmosDbEndpoint": "<your-CosmosDb-URI>",
"CosmosDbAuthKey": "<your-primary-key>",
"CosmosDbDatabaseId": "<your-database-id>",
"CosmosDbContainerId": "bot-storage"
Como instalar pacotes do Cosmos DB
Verifique se você tem os pacotes necessários para o Cosmos DB.
Instale o pacote NuGet Microsoft.Bot.Builder.Azure. Para obter mais informações sobre como usar o NuGet, confira Instalar e gerenciar pacotes no Visual Studio usando o Gerenciador de Pacotes do NuGet.
Implementação do Cosmos BD
Observação
A versão 4.6 introduziu um novo provedor de armazenamento do Cosmos DB, a classe de armazenamento particionado do Cosmos DB. A classe de armazenamento do Cosmos DB original foi preterida. Os contêineres criados com o armazenamento do Cosmos DB podem ser usados com o armazenamento particionado do Cosmos DB. Para obter mais informações, leia Particionamento no Azure Cosmos DB.
Ao contrário do armazenamento herdado do Cosmos DB, o armazenamento particionado do Cosmos DB não cria automaticamente um banco de dados dentro da sua conta do Cosmos DB. Você precisa criar um novo banco de dados manualmente, mas ignore a criação manual de um contêiner, pois o CosmosDbPartitionedStorage criará o contêiner para você.
O código de exemplo a seguir é executado usando o mesmo código de bot do exemplo de armazenamento de memória fornecido acima, excluindo as exceções listadas aqui. Os snippets de código a seguir mostram uma implementação de armazenamento do Cosmos DB para “myStorage” que substitui o armazenamento de memória local.
Primeiro, você precisa atualizar o Startup.cs para fazer referência à biblioteca bot builder do Azure:
using Microsoft.Bot.Builder.Azure;
Em seguida, no método ConfigureServices
em Startup.cs, crie o objeto CosmosDbPartitionedStorage
. Isso será passado para o construtor EchoBot
por meio da injeção de dependência.
// Use partitioned CosmosDB for storage, instead of in-memory storage.
services.AddSingleton<IStorage>(
new CosmosDbPartitionedStorage(
new CosmosDbPartitionedStorageOptions
{
CosmosDbEndpoint = Configuration.GetValue<string>("CosmosDbEndpoint"),
AuthKey = Configuration.GetValue<string>("CosmosDbAuthKey"),
DatabaseId = Configuration.GetValue<string>("CosmosDbDatabaseId"),
ContainerId = Configuration.GetValue<string>("CosmosDbContainerId"),
CompatibilityMode = false,
}));
No EchoBot.cs, altere a declaração _myStorage
da variável private static readonly MemoryStorage _myStorage = new MemoryStorage();
para o seguinte:
// variable used to save user input to CosmosDb Storage.
private readonly IStorage _myStorage;
Em seguida, passe o objeto IStorage
para o construtor EchoBot
:
public EchoBot(IStorage storage)
{
if (storage is null) throw new ArgumentNullException();
_myStorage = storage;
}
Inicie o bot do Cosmos DB
Execute o bot localmente.
Testar o bot do Cosmos DB com o Bot Framework Emulator
Agora inicie o Bot Framework Emulator e conecte-se ao seu bot:
- Selecione o link Criar nova configuração de bot na guia Boas-vindas do Emulator.
- Preencha os campos para se conectar ao seu bot considerando as informações na página da Web exibida ao iniciar o bot.
Interagir com o bot do Cosmos DB
Envie uma mensagem ao bot e o bot listará as mensagens recebidas por ele.
Exibir os dados do Cosmos DB
Depois de executar o bot e salvar suas informações, será possível visualizar os dados armazenados no portal do Azure na guia Data Explorer.
Usar o armazenamento de blobs
O Armazenamento de Blobs do Azure é uma solução de armazenamento de objetos da Microsoft para a nuvem. O armazenamento de Blobs é otimizado para armazenar grandes quantidades de dados não estruturados, como texto ou dados binários. Esta seção explica como criar uma conta e um contêiner de armazenamento de Blobs do Azure e, em seguida, como fazer referência ao contêiner de armazenamento de Blobs do bot.
Para obter mais informações sobre o armazenamento de Blobs, confira O que é o Armazenamento de Blobs do Azure?.
Criar sua conta de Armazenamento de Blobs
Para usar o Armazenamento de Blobs em seu bot, você precisará configurar algumas coisas antes de mexer no código.
No portal do Azure, selecione Todos os serviços.
Na seção Em destaque da página Todos os serviços, escolha Contas de armazenamento.
Na página Contas de armazenamento, escolha Nova.
No campo Assinatura, selecione a assinatura na qual você deseja criar a conta de armazenamento.
No campo Grupo de recursos, selecione um grupo de recursos existente ou selecione Criar novo e insira um nome para o novo grupo de recursos.
No campo Nome da conta de armazenamento, insira um nome para a conta. Observe as diretrizes abaixo:
- O nome deve ser exclusivo em todo o Azure.
- O nome precisa ter entre 3 e 24 caracteres.
- O nome pode conter apenas números e letras minúsculas.
No campo Local, selecione um local para a conta de armazenamento ou use o local padrão.
Nas demais configurações, configure o seguinte:
- Desempenho: Standard. Saiba mais sobre o desempenho.
- Tipo de conta: BlobStorage. Saiba mais sobre as contas de armazenamento.
- Duplicação: deixe a configuração padrão. Saiba mais sobre redundância.
Na seção Detalhes do projeto da página Criar conta de armazenamento, escolha os valores desejados para assinatura e Grupo de recursos.
Na seção Detalhes da instância da página Criar conta de armazenamento, insira o Nome da conta de armazenamento e escolha os valores de Localização, Tipo de conta e Duplicação.
Selecione Examinar + criar para conferir as configurações da conta de armazenamento.
Após a validação, selecione Criar.
Criar contêiner de Armazenamento de Blobs
Depois de criar sua conta de armazenamento de Blobs, abra-a e:
Selecione Gerenciador de Armazenamento (Preview).
Em seguida, clique com o botão direito do mouse em CONTÊINERES DE BLOBS
Selecione Criar contêiner de Blobs na lista suspensa.
Insira um nome no formulário Novo contêiner. Você usará esse nome para o valor "nome do contêiner de Blobs" para fornecer acesso à sua conta de Armazenamento de Blobs. Observe as diretrizes abaixo:
- O nome pode conter apenas letras minúsculas, números e hifens.
- O nome deve começar com uma letra ou um número.
- Cada hífen deve ser precedido e seguido por um caractere válido que não seja um hífen.
- O nome precisa ter entre 3 e 63 caracteres.
Adicionar informações de configuração do armazenamento de Blobs
Localize as chaves do armazenamento de Blobs necessárias para configurá-lo para o bot, conforme mostrado acima:
- No portal do Azure, abra sua conta de armazenamento de Blobs e escolha Chaves de acesso na seção Configurações.
- Para configurar o bot para acessar sua conta de armazenamento de Blobs, use Cadeia de conexão como o valor da cadeia de conexão de Blobs.
Adicione as informações a seguir ao arquivo de configuração.
appsettings.json
"BlobConnectionString": "<your-blob-connection-string>",
"BlobContainerName": "<your-blob-container-name>",
Como instalar pacotes de armazenamento de Blobs
Caso ainda não os tenha instalado, instale os pacotes a seguir.
Instale o pacote NuGet Microsoft.Bot.Builder.Azure.Blobs. Para obter mais informações, confira Instalar e gerenciar pacotes no Visual Studio usando o Gerenciador de Pacotes do NuGet.
Implementação do armazenamento de Blobs
O amazenamento de Blobs é usado para armazenar o estado do bot.
Observação
Microsoft.Bot.Builder.Azure.AzureBlobStorage
é preterido nas versões 4.10 e posteriores. Use o novo Microsoft.Bot.Builder.Azure.Blobs.BlobsStorage
em seu lugar.
O código de exemplo a seguir é executado usando o mesmo código de bot do exemplo de armazenamento de memória fornecido acima, excluindo as exceções listadas aqui.
Os snippets de código a seguir mostram uma implementação de armazenamento de Blobs para “myStorage” que substitui o armazenamento de memória local.
Primeiro, você precisa atualizar o Startup.cs para fazer referência à biblioteca de Blobs do bot builder do Azure:
Startup.cs
using Microsoft.Bot.Builder.Azure.Blobs;
Em seguida, no método ConfigureServices
em Startup.cs, crie o objeto BlobsStorage
, passando os valores de appsettings.json
. Isso será passado para o construtor EchoBot
por meio da injeção de dependência.
//Use Azure Blob storage, instead of in-memory storage.
services.AddSingleton<IStorage>(
new BlobsStorage(
Configuration.GetValue<string>("BlobConnectionString"),
Configuration.GetValue<string>("BlobContainerName")
));
Agora você primeiro precisa atualizar o EchoBot.cs para fazer referência à biblioteca de Blobs do bot builder do Azure:
EchoBot.cs
using Microsoft.Bot.Builder.Azure.Blobs;
Em seguida, remova ou comente a linha de código que cria a variável MemoryStorage 'private static readonly MemoryStorage _myStorage = new MemoryStorage();' e crie uma variável nova que será usada para salvar a entrada de usuário no Armazenamento de Blobs.
EchoBot.cs
// variable used to save user input to CosmosDb Storage.
private readonly IStorage _myStorage;
Em seguida, passe o objeto IStorage
para o construtor EchoBot
:
public EchoBot(IStorage storage)
{
if (storage is null) throw new ArgumentNullException();
_myStorage = storage;
}
Quando o armazenamento estiver definido para apontar para a conta de Armazenamento de Blobs, o código do bot armazenará e recuperará dados do Armazenamento de Blobs.
Quando o armazenamento estiver definido para apontar para a conta de Armazenamento de Blobs, o código do bot armazenará e recuperará dados do Armazenamento de Blobs.
Iniciar o bot de armazenamento de Blobs
Execute o bot localmente.
Iniciar o Emulator e conectar seu bot de armazenamento de Blobs
Em seguida, inicie o Emulator e, depois, conecte-se ao seu bot no Emulator:
- Selecione o link Criar nova configuração de bot na guia "Boas-vindas" do Emulator.
- Preencha os campos para se conectar ao seu bot considerando as informações na página da Web exibida ao iniciar o bot.
Interagir com seu bot de armazenamento de Blobs
Envie uma mensagem ao bot, e ele listará as mensagens recebidas.
Exibir seus dados de armazenamento de Blobs
Depois de executar o bot e salvar suas informações, poderemos exibi-lo na guia Gerenciador de Armazenamento no portal do Azure.
Armazenamento de transcrição de blobs
O armazenamento de transcrições do Blob do Azure fornece uma opção de armazenamento especializado que permite salvar e recuperar facilmente conversas do usuário como transcrições gravadas. O armazenamento de transcrições de Blobs do Azure é útil para capturar automaticamente as entradas de usuário para examinar durante a depuração do desempenho do seu bot.
Observação
Atualmente, o Python não oferece suporte ao armazenamento de transcrições de Blobs do Azure. Embora o JavaScript ofereça suporte ao armazenamento de transcrições de Blobs, as instruções a seguir são apenas para C#.
Configurar um contêiner de armazenamento de transcrições de Blobs
O armazenamento de transcrições do Blob do Azure pode usar a mesma conta de Armazenamento de Blobs criada seguindo as etapas detalhadas nas seções "Criar sua conta de Armazenamento de Blobs" e "Adicionar informações de configuração" acima. Agora, adicionamos um contêiner para manter nossas transcrições.
- Abra uma conta de Armazenamento de Blobs do Azure.
- Selecione o Gerenciador de Armazenamento.
- Clique com botão direito do mouse em CONTÊINERES DE BLOBS e selecione Criar contêiner de blobs.
- Insira um nome para o contêiner de transcrição e escolha OK. (Inserimos mybottranscripts)
Implementação de armazenamento de transcrições de Blobs
O código a seguir conecta o ponteiro de armazenamento de transcrição _myTranscripts
à sua nova conta de armazenamento de transcrições do Blob do Azure. Para criar esse link com um novo nome de contêiner, <your-blob-transcript-container-name>, cria um novo contêiner no Armazenamento de Blobs para manter os arquivos de transcrição.
O armazenamento de transcrições de Blobs foi projetado para armazenar transcrições de bot.
Observação
Microsoft.Bot.Builder.Azure.AzureBlobTranscriptStore
é preterido nas versões 4.10 e posteriores. Use o novo Microsoft.Bot.Builder.Azure.Blobs.BlobsTranscriptStore
em seu lugar.
echoBot.cs
using Microsoft.Bot.Builder.Azure.Blobs;
public class EchoBot : ActivityHandler
{
...
private readonly BlobsTranscriptStore _myTranscripts = new BlobsTranscriptStore("<your-azure-storage-connection-string>", "<your-blob-transcript-container-name>");
...
}
Armazenar conversas do usuário em transcrições de Blobs do Azure
Quando um contêiner de Blobs fica disponível para armazenar transcrições, você pode começar a armazenar as conversas dos usuários com seu bot. Essas conversas poderão ser usadas posteriormente como uma ferramenta de depuração para ver como os usuários interagem com o bot. Cada Reiniciar conversa do Emulator inicia a criação de uma nova lista de conversa de transcrição. O código a seguir preserva as entradas de conversas do usuário em um arquivo de transcrição armazenado.
- A transcrição atual é salva usando
LogActivityAsync
. - Transcrições salvas são recuperadas usando
ListTranscriptsAsync
. Nesse código de exemplo, a ID de cada transcrição armazenada é salva em uma lista chamada "storedTranscripts". Posteriormente, essa lista é usada para gerenciar a quantidade de transcrições armazenadas de blobs que podemos manter.
echoBot.cs
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
await _myTranscripts.LogActivityAsync(turnContext.Activity);
List<string> storedTranscripts = new List<string>();
PagedResult<Microsoft.Bot.Builder.TranscriptInfo> pagedResult = null;
var pageSize = 0;
do
{
pagedResult = await _myTranscripts.ListTranscriptsAsync("emulator", pagedResult?.ContinuationToken);
pageSize = pagedResult.Items.Count();
// transcript item contains ChannelId, Created, Id.
// save the channelIds found by "ListTranscriptsAsync" to a local list.
foreach (var item in pagedResult.Items)
{
storedTranscripts.Add(item.Id);
}
} while (pagedResult.ContinuationToken != null);
...
}
Gerenciar transcrições armazenadas de blobs
Embora as transcrições armazenadas possam ser usadas como uma ferramenta de depuração, ao longo do tempo, a quantidade de transcrições armazenadas poderá ficar maior do que você consegue preservar. O código adicional incluído abaixo usa DeleteTranscriptAsync
para remover tudo, exceto os três últimos itens de transcrição recuperados do seu armazenamento de transcrições de blobs.
echoBot.cs
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
await _myTranscripts.LogActivityAsync(turnContext.Activity);
List<string> storedTranscripts = new List<string>();
PagedResult<Microsoft.Bot.Builder.TranscriptInfo> pagedResult = null;
var pageSize = 0;
do
{
pagedResult = await _myTranscripts.ListTranscriptsAsync("emulator", pagedResult?.ContinuationToken);
pageSize = pagedResult.Items.Count();
// transcript item contains ChannelId, Created, Id.
// save the channelIds found by "ListTranscriptsAsync" to a local list.
foreach (var item in pagedResult.Items)
{
storedTranscripts.Add(item.Id);
}
} while (pagedResult.ContinuationToken != null);
// Manage the size of your transcript storage.
for (int i = 0; i < pageSize; i++)
{
// Remove older stored transcripts, save just the last three.
if (i < pageSize - 3)
{
string thisTranscriptId = storedTranscripts[i];
try
{
await _myTranscripts.DeleteTranscriptAsync("emulator", thisTranscriptId);
}
catch (System.Exception ex)
{
await turnContext.SendActivityAsync("Debug Out: DeleteTranscriptAsync had a problem!");
await turnContext.SendActivityAsync("exception: " + ex.Message);
}
}
}
...
}
Para obter mais informações sobre a classe, confira Armazenamento de transcrições de Blobs do Azure.
Informações Adicionais
Gerenciar simultaneidade usando eTags
Em nosso exemplo de código do bot, definimos a propriedade eTag
de cada IStoreItem
como *
. O membro (marca da entidade) eTag
do objeto de repositório é usado no Cosmos DB para gerenciar a simultaneidade. eTag
indica ao banco dados o que fazer caso outra instância do bot altere o objeto no mesmo armazenamento onde o bot está gravando.
A última gravação prevalece - permite substituições
Um valor da propriedade eTag
do asterisco (*
) indica que o último gravador prevalece. Ao criar um novo armazenamento de dados, é possível definir eTag
de uma propriedade como *
para indicar que os dados em gravação não foram salvos anteriormente, ou que você deseja que o último gravador substitua qualquer propriedade salva anteriormente. Se a simultaneidade não for um problema para o bot, a definição da propriedade eTag
como *
para qualquer dado que você esteja gravando viabilizará as substituições.
Manter simultaneidade e evitar substituições
Ao armazenar seus dados no Cosmos DB, use um valor diferente de *
para eTag
se quiser impedir o acesso simultâneo a uma propriedade e evitar a substituição de alterações por outra instância do bot. O bot receberá uma resposta de erro com a mensagem etag conflict key=
ao tentar salvar dados de estado se o eTag
não tiver o mesmo valor de eTag
em armazenamento.
Por padrão, o armazenamento do Cosmos DB verificará a propriedade eTag
de um objeto de armazenamento quanto à igualdade sempre que um bot gravar esse item e, em seguida, atualizará para um novo valor exclusivo após cada gravação. Se a propriedade eTag
na gravação não corresponder com eTag
no armazenamento, isso significa que outro bot ou thread alterou os dados.
Por exemplo, digamos que você queira que o bot edite uma nota salva, mas não quer que o bot substitua as alterações feitas por outra instância do bot. Se outra instância do bot tiver feito edições, você quer que o usuário edite a versão com as atualizações mais recentes.
Primeiro, crie uma classe que implemente IStoreItem
.
EchoBot.cs
public class Note : IStoreItem
{
public string Name { get; set; }
public string Contents { get; set; }
public string ETag { get; set; }
}
Em seguida, crie uma nota inicial criando um objeto de armazenamento e adicione o objeto ao armazenamento.
EchoBot.cs
// create a note for the first time, with a non-null, non-* ETag.
var note = new Note { Name = "Shopping List", Contents = "eggs", ETag = "x" };
var changes = Dictionary<string, object>();
{
changes.Add("Note", note);
};
await NoteStore.WriteAsync(changes, cancellationToken);
Então, acesse e atualize a nota mais tarde, mantendo eTag
que foi lido no armazenamento.
EchoBot.cs
var note = NoteStore.ReadAsync<Note>("Note").Result?.FirstOrDefault().Value;
if (note != null)
{
note.Contents += ", bread";
var changes = new Dictionary<string, object>();
{
changes.Add("Note1", note);
};
await NoteStore.WriteAsync(changes, cancellationToken);
}
Se a nota foi atualizada no armazenamento antes de gravar as alterações, a chamada para Write
lançará uma exceção.
Para manter a simultaneidade, sempre leia uma propriedade do armazenamento e modifique a propriedade lida para que eTag
seja mantido. Ao ler os dados de usuário do armazenamento, a resposta conterá a propriedade eTag. Se você alterar os dados e gravar dados atualizados no armazenamento, a solicitação deverá incluir a propriedade eTag que especifica o mesmo valor lido anteriormente. No entanto, gravar um objeto com eTag
definido para *
permitirá que a gravação substitua quaisquer outras alterações.
Próximas etapas
Agora que você sabe como ler e gravar diretamente do armazenamento, veremos como é possível utilizar o gerenciador de estado para fazer isso.