ストレージに直接書き込むWrite directly to storage

適用対象: 対象 SDK v4 対象外 SDK v3 APPLIES TO: yesSDK v4 no SDK v3

ミドルウェアまたはコンテキスト オブジェクトを使用せずに、ストレージ オブジェクトに対して直接読み取りや書き込みを行うことができます。You can read and write directly to your storage object without using middleware or context object. ボットが会話の保持に使用するデータ、またはボットの会話フロー外にあるソースのデータについては、この方法が適切な可能性があります。This can be appropriate for data your bot uses to preserve a conversation, or data that comes from a source outside your bot's conversation flow. このデータ ストレージ モデルでは、データは、状態マネージャーを使用せずに、ストレージから直接データを読み取られます。In this data storage model, data is read it directly from storage instead of using a state manager. この記事のコード例では、メモリ ストレージCosmos DBBlob Storage、および Azure Blob Transcript Store を使用してストレージに対するデータの読み取りや書き込みを行う方法を示します。The code examples in this article show you how to read and write data to storage using Memory Storage, Cosmos DB, Blob Storage, and Azure Blob Transcript Store.

前提条件Prerequisites

  • Azure サブスクリプションをお持ちでない場合は、開始する前に無料アカウントを作成してください。If you don't have an Azure subscription, create a free account before you begin.
  • 記事に関する知識: dotnet または nodeJS 用にボットをローカルで作成します。Familiarity with article: Create a bot locally for dotnet or nodeJS.
  • C#テンプレート または nodeJS および yeoman 用の Bot Framework SDK v4 テンプレート。Bot Framework SDK v4 template for C# template or nodeJS and yeoman.

このサンプルについてAbout this sample

この記事のサンプル コードは、基本的なエコー ボットの構造で始まり、コードを追加することでそのボットの機能を拡張します (下記を参照)。The sample code in this article begins with the structure of a basic echo bot, then extends that bot's functionality by adding additional code (provided below). 拡張されたこのコードにより、受信したユーザー入力が保持されるリストが作成されます。This extended code creates a list to preserve user inputs as they are received. ユーザー入力の完全なリストは、ターンごとにユーザーにエコー バックされます。Each turn, the full list of user inputs is echoed back to the user. この入力リストを含むデータ構造は、その後、そのターンの最後にストレージに保存されます。The data structure containing this list of inputs is then saved to storage at the end of that turn. このサンプル コードには追加機能が追加されているため、さまざまな種類のストレージについて説明します。Various types of storage are explored as additional funtionality is added to this sample code.

メモリ ストレージMemory storage

Bot Framework SDK を使用すると、メモリ内ストレージを使用してユーザー入力を格納することができます。The Bot Framework SDK allows you to store user inputs using in-memory storage. メモリ ストレージはテストにのみ使用され、実稼働を目的としたものではありません。Memory storage is used for testing purposes only and is not intended for production use. データベース ストレージなどの永続的なストレージ類は運用環境のボットに最適です。Persistent storage types, such as database storage, are best for production bots. ボットを発行する前に、ストレージを Cosmos DB または Blob Storage に設定してください。Be sure to set storage to Cosmos DB or Blob Storage before publishing your bot.

基本のボットを作成するBuild a basic bot

このトピックの残りの部分では、エコー ボットについては取り上げません。The rest of this topic builds off of an Echo bot. エコー ボットのサンプル コードをローカルでビルドするには、C# EchoBot または JS EchoBot のいずれかをビルドするためのクイック スタート手順に従ってください。The Echo bot sample code can be locally built by following the Quickstart instructions for building either a C# EchoBot or a JS EchoBot.

EchoBot.csEchoBot.cs

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 logitems 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 occured.
         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 occured.
            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 occured.
            await turnContext.SendActivityAsync("Sorry, something went wrong storing your message!");
         }
      }
      ...  // OnMessageActivityAsync( )
   }
}

ボットの起動Start your bot

ボットをローカルで実行します。Run your bot locally.

エミュレーターの起動とボットの接続Start the emulator and connect your bot

  • Bot Framework Emulator をインストールしてから、エミュレーターを起動し、そのエミュレーターのボットに接続します。Install the Bot Framework Emulator Next, start the emulator and then connect to your bot in the emulator:
  1. エミュレーターの [ようこそ] タブにある [新しいボット構成を作成する] リンクをクリックします。Click the Create new bot configuration link in the emulator "Welcome" tab.
  2. ボットを起動したときに表示される Web ページの情報を踏まえ、ご自身のボットに接続するためのフィールドに入力します。Fill in fields to connect to your bot, given the information on the webpage displayed when you started your bot.

ボットでのやり取りInteract with your bot

メッセージをお使いのボットに送信します。Send a message to your bot. ボットには、受信したメッセージが一覧表示されます。The bot will list the messages it has received.

エミュレーター テスト ストレージ ボット

Cosmos DB の使用Using Cosmos DB

メモリ ストレージを使用しているので、Azure Cosmos DB を使用するようにコードを更新します。Now that you've used memory storage, we'll update the code to use Azure Cosmos DB. Cosmos DB は、Microsoft のグローバル分散型マルチモデル データベースです。Cosmos DB is Microsoft's globally distributed, multi-model database. Azure Cosmos DB では、Azure のリージョンをいくつでもまたいでスループットとストレージを柔軟かつ個別にスケーリングすることができます。Azure Cosmos DB enables you to elastically and independently scale throughput and storage across any number of Azure's geographic regions. このサービスは包括的なサービス レベル アグリーメント (SLA) により、スループット、待機時間、可用性、一貫性が保証されています。It offers throughput, latency, availability, and consistency guarantees with comprehensive service level agreements (SLAs).

セットアップSet up

ボットで Cosmos DB を使用するには、コードに取り組む前に、いくつかの設定を行う必要があります。To use Cosmos DB in your bot, you'll need to get a few things set up before getting into the code. Cosmos DB のデータベースとアプリ作成の詳細については、こちらの Cosmos DB dotnet または Cosmos DB nodejs に関するドキュメントを参照してください。For an in-depth description of Cosmos DB database and app creation access the documentation here for Cosmos DB dotnet or Cosmos DB nodejs.

データベース アカウントの作成Create your database account

  1. 新しいブラウザー ウィンドウで、Azure Portal にサインインします。In a new browser window, sign in to the Azure portal.

Cosmos DB データベースの作成

  1. [リソースの作成]、[データベース]、[Azure Cosmos DB] の順にクリックします。Click Create a resource > Databases > Azure Cosmos DB

Cosmos DB の[新規アカウント] ページ

  1. [新規アカウント] ページで、[サブスクリプション] および [リソース グループ] に情報を指定します。On the New account page, provide Subscription, Resource group information. [アカウント名] フィールドに一意の名前を指定します。この名前は、最終的にはご自身のデータ アクセス URL の一部になります。Create a unique name for your Account Name field - this eventually becomes part of your data access URL name. API には Core(SQL) を選択し、データ アクセス時間を短縮するために近くの場所を指定します。For API, select Core(SQL), and provide a nearby Location to improve data access times.
  2. 次に、[確認および作成] をクリックします。Then click Review + Create.
  3. 検証が適切に行われたら、[作成] をクリックします。Once validation has been successful, click Create.

アカウントの作成には数分かかります。The account creation takes a few minutes. ポータルに "Wait for the portal to display the Congratulations! Azure Cosmos DB アカウントが作成されました" ページが表示されるまで待機します。Your Azure Cosmos DB account was created page.

コレクションの追加Add a collection

Cosmos DB コレクションの追加

  1. [設定]、[新しいコレクション] の順にクリックします。Click Settings > New Collection. [コレクションの追加] 領域が右端に表示されます。表示するには、右にスクロールする必要がある場合があります。The Add Collection area is displayed on the far right, you may need to scroll right to see it. Cosmos DB が最近更新されたため、/id でパーティション キーを 1 つ必ず追加します。このキーにより、クロス パーティション クエリのエラーが回避されます。Due to recent updates to Cosmos DB, be sure to add a single Partition key: /id. This key will avoid cross partition query errors.

Cosmos DB

  1. 新しいデータベース コレクションは "bot-cosmos-sql-db" です。コレクション ID は "bot-storage" になります。Your new database collection, "bot-cosmos-sql-db" with a collection id of "bot-storage." これらの値は、以降に示すコード例で使用します。We will use these values in our coding example that follows below.

Cosmos DB のキー

  1. データベース設定の [キー] タブで、エンドポイント URI とキーが利用可能になります。The endpoint URI and key are available within the Keys tab of your database settings. これらの値は、この記事の後半のコードの構成で必要になります。These values will be needed to configure your code further down in this article.

構成情報の追加Add configuration information

Cosmos DB ストレージを追加するための構成データは短くシンプルなものであり、ボットがより複雑になった場合でも、同じ方法を使用して構成設定を追加できます。Our configuration data to add Cosmos DB storage is short and simple, you can add additional configuration settings using these same methods as your bot gets more complex. この例では、上記の例の Cosmos DB データベースとコレクションの名前を使用します。This example uses the Cosmos DB database and collection names from the example above.

EchoBot.csEchoBot.cs

public class EchoBot : ActivityHandler
{
   private const string CosmosServiceEndpoint = "<your-cosmos-db-URI>";
   private const string CosmosDBKey = "<your-cosmos-db-account-key>";
   private const string CosmosDBDatabaseName = "bot-cosmos-sql-db";
   private const string CosmosDBCollectionName = "bot-storage";
   ...
   
}

パッケージのインストールInstalling packages

Cosmos DB に必要なパッケージがあることを確認します。Make sure you have the packages necessary for Cosmos DB

Install-Package Microsoft.Bot.Builder.Azure

実装Implementation

次のサンプル コードは、上記のメモリ ストレージのサンプルと同じボット コードを使用して実行されます。The following sample code runs using the same bot code as the memory storage sample provided above. 次のコード スニペットは、ローカルのメモリ ストレージを置き換える "myStorage" に対する Cosmos DB ストレージの実装を示しています。The code snippet below shows an implementation of Cosmos DB storage for 'myStorage' that replaces local Memory storage. メモリ ストレージはコメント アウトされ、Cosmos DB への参照で置き換えられています。Memory Storage is commented out and replaced with a reference to Cosmos DB.

EchoBot.csEchoBot.cs


using System;
...
using Microsoft.Bot.Builder.Azure;
...
public class EchoBot : ActivityHandler
{
   // Create local Memory Storage - commented out.
   // private static readonly MemoryStorage _myStorage = new MemoryStorage();

   // Replaces Memory Storage with reference to Cosmos DB.
   private static readonly CosmosDbStorage _myStorage = new CosmosDbStorage(new CosmosDbStorageOptions
   {
      AuthKey = CosmosDBKey,
      CollectionId = CosmosDBCollectionName,
      CosmosDBEndpoint = new Uri(CosmosServiceEndpoint),
      DatabaseId = CosmosDBDatabaseName,
   });
   
   ...
}

ボットの起動Start your bot

ボットをローカルで実行します。Run your bot locally.

Bot Framework Emulator でのボットのテストTest your bot with bot framework emulator

Bot Framework Emulator を起動して、ご自身のボットに接続します。Now start your bot framework emulator and connect to your bot:

  1. エミュレーターの [ようこそ] タブにある [新しいボット構成を作成する] リンクをクリックします。Click the Create new bot configuration link in the emulator "Welcome" tab.
  2. ボットを起動したときに表示される Web ページの情報を踏まえ、ご自身のボットに接続するためのフィールドに入力します。Fill in fields to connect to your bot, given the information on the webpage displayed when you started your bot.

ボットでのやり取りInteract with your bot

メッセージをボットに送信します。ボットは受信したメッセージを表示します。Send a message to your bot, and the bot will list the messages it received. 実行中のエミュレーターEmulator running

データの表示View your data

ボットを実行して情報を保存した後は、Azure portal の [データ エクスプローラー] タブで、格納データを表示できます。After you have run your bot and saved your information, we can view the data stored in the Azure portal under the Data Explorer tab.

データ エクスプローラーの例

Blob Storage の使用Using Blob storage

Azure Blob Storage は、Microsoft のクラウド用オブジェクト ストレージ ソリューションです。Azure Blob storage is Microsoft's object storage solution for the cloud. BLOB ストレージは、テキスト データやバイナリ データなどの大量の非構造化データを格納するために最適化されています。Blob storage is optimized for storing massive amounts of unstructured data, such as text or binary data.

Blob Storage アカウントの作成Create your Blob storage account

ボットで Blob Storage を使用するには、コードに取り組む前に、いくつかの設定を行う必要があります。To use Blob storage in your bot, you'll need to get a few things set up before getting into the code.

  1. 新しいブラウザー ウィンドウで、Azure Portal にサインインします。In a new browser window, sign in to the Azure portal.

Blob Storage の作成

  1. [リソースの作成]、[Storage]、[ストレージ アカウント - Blob、File、Table、Queue] の順にクリックします。Click Create a resource > Storage > Storage account - blob, file, table, queue

Blob Storage の [新規アカウント] ページ

  1. [新規アカウント] ページで、ストレージ アカウントの [名前] を入力し、[アカウントの種類] として [Blob ストレージ] を選択し、[場所][リソース グループ]、および [サブスクリプション] の情報を指定します。In the New account page, enter Name for the storage account, select Blob storage for Account kind, provide Location, Resource group and Subscription infomration.
  2. 次に、[確認および作成] をクリックします。Then click Review + Create.
  3. 検証が適切に行われたら、[作成] をクリックします。Once validation has been successful, click Create.

Blob Storage コンテナーの作成Create Blob storage container

ご自身の Blob storage アカウントが作成されたら、次の手順でこのアカウントを開きますOnce your Blob storage account is created, open this account by

  1. リソースを選択します。Selecting the resource.
  2. Storage Explorer (プレビュー) を使用して "オープン" しますNow "Open" using Storage Explorer (preview)

Blob Storage コンテナーの作成

  1. [BLOB コンテナー] を右クリックし、"BLOB コンテナーの作成" を選択します。Right click BLOB CONTAINERS, select Create blob container.
  2. メモを追加します。Add a name. Blob Storage アカウントにアクセスできるようにするには、"your-blob-storage-container-name" の値にこの名前を使用します。You will use this name for the value "your-blob-storage-container-name" to provide access to your Blob Storage account.

構成情報の追加Add configuration information

上記のボットの Blob Storage の構成に必要な Blob Storage キーを検索します。Find the Blob Storage keys you need to configure Blob Storage for your bot as shown above:

  1. Azure portal で、Blob Storage アカウントを開き、[設定]、[アクセス キー] の順に選択します。In the Azure portal, open your Blob Storage account and select Settings > Access keys.

Blob Storage キーの検索

Blob Storage アカウントにアクセスできるようにするには、"your-blob-storage-account-string" の値に key1 Connection string を使用します。We will use key1 Connection string as the value "your-blob-storage-account-string" to provide access to your Blob Storage account.

パッケージのインストールInstalling packages

Cosmos DB を使用するには、次のパッケージをインストールします (まだインストールされていない場合)。If not previously installed to use Cosmos DB, install the following packages.

Install-Package Microsoft.Bot.Builder.Azure

実装Implementation

EchoBot.csEchoBot.cs

using Microsoft.Bot.Builder.Azure;

"myStorage" が既存の Blob Storage アカウントを指すようにコード行を更新します。Update the line of code that points "myStorage" to your existing Blob Storage account.

EchoBot.csEchoBot.cs

private static readonly AzureBlobStorage _myStorage = new AzureBlobStorage("<your-blob-storage-account-string>", "<your-blob-storage-container-name>");

ご自身の Blob Storage アカウントを指すようにストレージが設定されると、お使いのボット コードは Blob Storage からデータを保存および取得するようになります。Once your storage is set to point to your Blob Storage account, your bot code will now store and retrieve data from Blob Storage.

ボットの起動Start your bot

ボットをローカルで実行します。Run your bot locally.

エミュレーターの起動とボットの接続Start the emulator and connect your bot

次に、エミュレーターを起動し、エミュレーターのボットに接続します。Next, start the emulator and then connect to your bot in the emulator:

  1. エミュレーターの [ようこそ] タブにある [新しいボット構成を作成する] リンクをクリックします。Click the Create new bot configuration link in the emulator "Welcome" tab.
  2. ボットを起動したときに表示される Web ページの情報を踏まえ、ご自身のボットに接続するためのフィールドに入力します。Fill in fields to connect to your bot, given the information on the webpage displayed when you started your bot.

ボットでのやり取りInteract with your bot

メッセージをボットに送信すると、受信したメッセージがボットに一覧表示されます。Send a message to your bot, and the bot will list the messages it receives.

エミュレーター テスト ストレージ ボット

データの表示View your data

ボットを実行して情報を保存したら、Azure portal の [ストレージ エクスプローラー] タブの下にその情報を表示できます。After you have run your bot and saved your information, we can view it in under the Storage Explorer tab in the Azure portal.

Blob トランスクリプト ストレージBlob transcript storage

Azure Blob トランスクリプト ストレージには、特殊なストレージ オプションが用意されています。このオプションを使用すると、記録されたトランスクリプトの形式でユーザーの会話を簡単に保存および取得できます。Azure blob transcript storage provides a specialized storage option that allows you to easily save and retrieve user conversations in the form of a recorded transcript. Azure Blob トランスクリプト ストレージは、ボットのパフォーマンスをデバッグする際に、調べるユーザー入力を自動的にキャプチャする場合に特に便利です。Azure blob transcript storage is particularly useful for automatically capturing user inputs to examine while debugging your bot's performance.

セットアップSet up

Azure Blob トランスクリプト ストレージでは、上記の「Blob Storage アカウントの作成」および「構成情報の追加」の手順に従って作成したのと同じ Blob Storage アカウントを使用できます。Azure blob transcript storage can use the same blob storage account created following the steps detailed in sections "Create your blob storage account" and "Add configuration information" above. ここで、トランスクリプトを保持するためのコンテナーを追加しますWe now add a container to hold our transcripts

トランスクリプト コンテナーの作成

  1. Azure Blob Storage アカウントを開きます。Open your Azure blob storage account.
  2. "Storage Explorer" をクリックします。Click on Storage Explorer.
  3. "BLOB コンテナー" を右クリックし、"BLOB コンテナーの作成" を選択します。Right click on BLOB CONTAINERS and select create blob container.
  4. トランスクリプト コンテナーの名前を入力し、[OK] を選択します enter a name for your transcript container and then select OK. (mybottranscripts を入力しました)。(We entered mybottranscripts)

実装Implementation

次のコードでは、トランスクリプト ストレージのポインター _myTranscripts を新しい Azure Blob トランスクリプト ストレージ アカウントに接続します。The following code connects transcript storage pointer _myTranscripts to your new Azure blob transcript storage account. 新しいコンテナー名 でこのリンクを作成するには、トランスクリプト ファイルを保持する新しいコンテナーを Blob Storage に作成します。To create this link with a new container name, , creates a new container within Blob storage to hold your transcript files.

echoBot.csechoBot.cs

using Microsoft.Bot.Builder.Azure;

public class EchoBot : ActivityHandler
{
   ...
   
   private readonly AzureBlobTranscriptStore _myTranscripts = new AzureBlobTranscriptStore("<your-blob-transcript-storage-account-string>", "<your-blob-transcript-container-name>");
   
   ...
}

Azure Blob トランスクリプトへのユーザーの会話の保存Store user conversations in azure blob transcripts

BLOB コンテナーでトランスクリプトを保存できるようになったら、ボットとユーザーの会話の保持を開始できます。After a blob container is available to store transcripts you can begin to preserve your users' conversations with your bot. このような会話を後からデバッグ ツールとして使用しすると、ユーザーがボットとどのようにやり取りするかを確認できます。These conversations can later be used as a debugging tool to see how users interact with your bot. 各エミュレーター "会話の再開" によって、新しいトランスクリプト会話リストの作成が開始されます。Each emulator Restart conversation initiates the creation of a new transcript conversation list. 次のコードでは、ユーザーの会話の入力を、保存されているトランスクリプト ファイルに保持します。The following code preserves user conversation inputs within a stored transcript file.

  • 現在のトランスクリプトは LogActivityAsync を使用して保存されます。The current transcript is saved using LogActivityAsync.
  • 保存されたトランスクリプトは ListTranscriptsAsync を使用して取得されます。Saved transcripts are retrieved using ListTranscriptsAsync. このサンプル コードでは、保存されている各トランスクリプトの ID が "storedTranscripts" という名前のリストに保存されます。In this sample code the Id of each stored transcript is saved into a list named "storedTranscripts". このリストは後で、保持する保存済み BLOB トランスクリプトの数を管理するときに使用します。This list is later used to manage the number of stored blob transcripts we retain.

echoBot.csechoBot.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);
    
    ...
}

保存済み BLOB トランスクリプトの管理Manage stored blob transcripts

保存済みトランスクリプトをデバッグ ツールとして使用できると、保存済みトランスクリプトの数が時間経過と共に増加し、保持したい数を超えることがあります。While stored transcripts can be used as a debugging tool, over time the number of stored transcripts can grow larger than you care to preserve. 以下の追加コードでは、DeleteTranscriptAsync を使用して、取得された最新の 3 つのトランスクリプト項目を除くすべての項目を、BLOB トランスクリプト ストアから削除します。The additional code included below uses DeleteTranscriptAsync to remove all but the last three retrieved transcript items from your blob transcript store.

echoBot.csechoBot.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);
           }
       }
    }
    ...
}

次に示すリンク先には、Azure Blob トランスクリプト ストレージに関するその他の情報が記載されていますThe following link provides more information concerning Azure Blob Transcript Storage

追加情報Additional Information

eTag を使用してコンカレンシーを管理するManage concurrency using eTags

ボット コード例では、各 IStoreItemeTag プロパティを * に設定します。In our bot code example we set the eTag property of each IStoreItem to *. ストア オブジェクトの eTag (エンティティ タグ) メンバーは、コンカレンシーを管理するために Cosmos DB 内で使用されます。The eTag (entity tag) member of your store object is used within Cosmos DB to manage concurrency. eTag は、自分のボットが書き込んでいる同じストレージ内のオブジェクトをボットの別のインスタンスが変更した場合の対処方法をデータベースに通知します。The eTag tells your database what to do if another instance of the bot has changed the object in the same storage that your bot is writing to.

最後の書き込みが有効 - 上書きを許可するLast write wins - allow overwrites

eTag プロパティの値にアスタリスク (*) を指定すると、最後の書き込みが有効であることを示します。An eTag property value of asterisk (*) indicates that the last writer wins. 新しいデータ ストアを作成するときは、プロパティの eTag* に設定して、以前に保存したことのないデータを書き込んでいること、または以前に保存されたすべてのプロパティを最後の書き込みで上書きすることを示します。When creating a new data store, you can set eTag of a property to * to indicate that you have not previously saved the data that you are writing, or that you want the last writer to overwrite any previously saved property. コンカレンシーがボットにとって問題にならない場合は、書き込んでいるすべてのデータについて eTag プロパティを * に設定して上書きを許可します。If concurrency is not an issue for your bot, setting the eTag property to * for any data that you are writing enables overwrites.

コンカレンシーを維持して上書きを禁止するMaintain concurrency and prevent overwrites

データを Cosmos DB に保存する際に、プロパティへの同時アクセスを禁止し、変更をボットの別のインスタンスによって上書きされないようにする場合は、* 以外の値を eTag に使います。When storing your data into Cosmos DB, use a value other than * for the eTag if you want to prevent concurrent access to a property and avoid overwriting changes from another instance of the bot. ボットが状態データを保存しようとして、eTag がストレージ内の eTag と同じ値でない場合、ボットは etag conflict key= というメッセージのエラー応答を受け取ります。The bot receives an error response with the message etag conflict key= when it attempts to save state data and the eTag is not the same value as the eTag in storage.

既定では、Cosmos DB ストアはボットがストレージ オブジェクトを書き込むたびにその項目の eTag プロパティが等しいかどうかを確認し、各書き込みの後で新しい一意の値に更新します。By default, the Cosmos DB store checks the eTag property of a storage object for equality every time a bot writes to that item, and then updates it to a new unique value after each write. 書き込みの eTag プロパティがストレージの eTag と一致しない場合は、別のボットまたはスレッドがデータを変更したことを意味します。If the eTag property on write doesn't match the eTag in storage, it means another bot or thread changed the data.

たとえば、保存されたメモをボットで編集しますが、ボットの別のインスタンスが行った変更を上書きしないようにする必要があるものとします。For example, let's say you want your bot to edit a saved note, but you don't want your bot to overwrite changes that another instance of the bot has done. ボットの別のインスタンスが編集を行った場合は、ユーザーに最新の更新でバージョンを編集させます。If another instance of the bot has made edits, you want the user to edit the version with the latest updates.

最初に、IStoreItem を実装するクラスを作成します。First, create a class that implements IStoreItem.

EchoBot.csEchoBot.cs

public class Note : IStoreItem
{
    public string Name { get; set; }
    public string Contents { get; set; }
    public string ETag { get; set; }
}

次に、ストレージ オブジェクトを作成することによって最初のメモを作成し、オブジェクトをストアに追加します。Next, create an initial note by creating a storage object, and add the object to your store.

EchoBot.csEchoBot.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);

後でメモにアクセスして更新し、ストアから読み取ったその eTag を維持します。Then, access and update the note later, keeping its eTag that you read from the store.

EchoBot.csEchoBot.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);
}

変更を書き込む前にストアのメモが更新されていた場合、Write の呼び出しでは例外がスローされます。If the note was updated in the store before you write your changes, the call to Write will throw an exception.

コンカレンシーを維持するには、常にストレージからプロパティを読み取った後、読み取ったプロパティを変更して、eTag が維持されるようにします。To maintain concurrency, always read a property from storage, then modify the property you read, so that the eTag is maintained. ストアからユーザー データを読み取る場合、応答には eTag プロパティが含まれます。If you read user data from the store, the response will contain the eTag property. データを変更して更新後のデータをストアに書き込む場合、要求に含まれる eTag プロパティでは、前に読み取ったのと同じ値が指定されている必要があります。If you change the data and write updated data to the store, your request should include the eTag property that specifies the same value as you read earlier. ただし、eTag* に設定してオブジェクトを書き込むと、書き込みで他の変更を上書きできます。However, writing an object with its eTag set to * will allow the write to overwrite any other changes.

次の手順Next steps

ストレージを直接読み書きする方法がわかったので、状態マネージャーを使ってそれを行う方法を確認してください。Now that you know how to read read and write directly from storage, lets take a look at how you can use the state manager to do that for you.