直接寫入記憶體
適用於: SDK v4
您可以直接讀取和寫入記憶體物件,而不需使用中間件或內容物件。 這適用於 Bot 用來保留交談的數據,或來自 Bot 交談流程外部來源的數據。 在此數據記憶體模型中,數據會直接從記憶體讀取,而不是使用狀態管理員。 本文中的程式代碼範例示範如何使用記憶體、Cosmos DB、Azure Blob 和 Azure Blob 文字記錄記憶體,將數據讀取和寫入記憶體。
注意
Bot Framework JavaScript、C# 和 Python SDK 將會繼續受到支援,不過,Java SDK 即將淘汰,最終長期支援將於 2023 年 11 月結束。
使用 Java SDK 建置的現有 Bot 將繼續運作。
針對新的 Bot 建置,請考慮使用 Microsoft Copilot Studio ,並閱讀 選擇正確的 Copilot 解決方案。
如需詳細資訊,請參閱 Bot 建置的未來。
必要條件
- 如果您沒有 Azure 訂用帳戶,請在開始前建立免費帳戶。
- 熟悉在 本機建立 Bot 。
- 適用於 Visual Studio 的 Bot Framework SDK v4 範本(C#)、 Node.js或 Yeoman。
注意
您可以從 Visual Studio 內安裝範本。
- 在功能表中,選取 [擴充功能],然後選取 [管理擴充功能]。
- 在 [ 管理延伸模組 ] 對話框中,搜尋並安裝 適用於Visual Studio的 Bot Framework v4 SDK 範本。
如需將 .NET Bot 部署至 Azure 的相關信息,請參閱如何 布建和發佈 Bot。
關於此範例
本文中的範例程式代碼從基本回應 Bot 的結構開始,然後藉由新增其他程式代碼來擴充 Bot 的功能(如下所示)。 此擴充程式代碼會建立清單,以在收到使用者輸入時保留使用者輸入。 每個回合,儲存至記憶體的使用者輸入完整清單都會回顯給使用者。 然後修改包含此輸入清單的數據結構,以儲存至記憶體。 隨著將其他功能新增至此範例程式代碼,會探索各種類型的記憶體。
記憶體記憶體
Bot Framework SDK 可讓您使用記憶體內部記憶體來儲存使用者輸入。 由於每次重新啟動 Bot 時都會清除記憶體內部記憶體,因此最適合用於測試目的,且不適合用於生產環境。 持續性記憶體類型,例如資料庫記憶體,最適合生產 Bot。
建置基本 Bot
本主題的其餘部分會建置回 Echo Bot。 您可以遵循建立 Bot 的快速入門指示,在本機建置 Echo Bot 範例程式代碼。
以下列程式代碼取代 EchoBot.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 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!");
}
}
}
}
啟動 Bot
在本機執行 Bot。
啟動模擬器並連線 Bot
安裝 Bot Framework Emulator Next、啟動模擬器,然後在模擬器中連線到您的 Bot:
- 在 [模擬器歡迎使用] 索引標籤中選取 [建立新的 Bot 組態] 連結。
- 填入欄位以連線到您的 Bot,指定您啟動 Bot 時所顯示網頁上的資訊。
與您的 Bot 互動
將訊息傳送至 Bot。 Bot 會列出已接收的訊息。
本文的其餘部分將示範如何儲存至持續性記憶體,而不是 Bot 的內部記憶體。
使用 Cosmos DB
重要
Cosmos DB 記憶體類別已被取代。 原本使用 CosmosDbStorage 建立的容器沒有分割區索引鍵集,而且已獲得 _/partitionKey 的預設分割區索引鍵。
使用 Cosmos DB 記憶體 建立的容器可以搭配 Cosmos DB 分割記憶體使用。 如需詳細資訊,請參閱 Azure Cosmos DB 中的數據分割。
另請注意,與舊版 Cosmos DB 記憶體不同,Cosmos DB 分割記憶體不會自動在您的 Cosmos DB 帳戶內建立資料庫。 您必須 手動建立新的資料庫,但請略過手動建立容器,因為 CosmosDbPartitionedStorage 會為您建立容器。
現在您已使用記憶體記憶體記憶體,我們將更新程式代碼以使用 Azure Cosmos DB。 Cosmos DB 是Microsoft全域散發的多模型資料庫。 Azure Cosmos DB 可讓您彈性且獨立地跨任意數目的 Azure 地理區域調整輸送量和記憶體。 它提供輸送量、延遲、可用性和一致性保證,並提供完整的服務等級協定(SLA)。
設定 Cosmos DB 資源
若要在 Bot 中使用 Cosmos DB,您必須先建立資料庫資源,才能進入程式代碼。 如需 Cosmos DB 資料庫和應用程式建立的深入描述,請參閱 .NET、Node.js 或 Python 的快速入門。
建立資料庫帳戶
移至 Azure 入口網站 以建立 Azure Cosmos DB 帳戶。 搜尋並選取 [Azure Cosmos DB]。
在 [ Azure Cosmos DB ] 頁面中,選取 [ 新增 ] 以顯示 [ 建立 Azure Cosmos DB 帳戶 ] 頁面。
提供下列欄位的值︰
- 訂用帳戶。 選取要用於此 Azure Cosmos 帳戶的 Azure 訂用帳戶。
- 資源群組。 選取現有的資源群組或選取 [新建],然後輸入新資源群組的名稱。
- 帳戶名稱。 輸入名稱來識別您的 Azure Cosmos 帳戶。 因為 documents.azure.com 會附加到您所提供的名稱以建立 URI,請使用唯一名稱。 請注意下列指導方針:
- 名稱在整個 Azure 中必須是唯一的。
- 名稱長度必須介於 3 到 31 個字元之間。
- 名稱只能包含小寫字母、數位和連字元 (-) 字元。
- API。 選取 Core(SQL)
- 位置。 選取最接近使用者的位置,讓他們能夠快速存取數據。
選取 [檢閱 + 建立] 。
驗證後,選取 [建立]。
建立帳戶需要幾分鐘。 等候入口網站顯示 [恭喜!已建立您的 Azure Cosmos DB 帳戶] 頁面。
加入資料庫
注意
請勿自行建立容器。 Bot 會在建立其內部 Cosmos DB 用戶端時為您建立它,確保其已正確設定以儲存 Bot 狀態。
流覽至新建立 Cosmos DB 帳戶內的 [數據總管] 頁面,然後從 [新增容器] 下拉式清單中選擇 [新增資料庫]。 然後,面板會在視窗右側開啟,您可以在其中輸入新資料庫的詳細數據。
輸入新資料庫的標識碼,並選擇性地設定輸送量(您稍後可以變更此標識符),最後選取 [ 確定 ] 以建立資料庫。 請記下此資料庫標識碼,以供稍後在設定 Bot 時使用。
既然您已建立 Cosmos DB 帳戶和資料庫,您必須複製一些值,以將新資料庫整合到 Bot 中。 若要擷取這些專案,請流覽至 Cosmos DB 帳戶資料庫設定區段中的 [金鑰 ] 索引標籤。 從此頁面,您將需要您的 URI(Cosmos DB 端點)和 PRIMARY KEY(授權金鑰)。
您現在應該會有具有資料庫的 Cosmos DB 帳戶,且下列值已準備好在 Bot 設定中使用。
- URI
- 主索引鍵
- 資料庫識別碼
新增 Cosmos DB 組態資訊
使用您在本文上一個部分中記下的詳細數據,來設定您的端點、授權密鑰和資料庫識別碼。 最後,您應該為將在資料庫內建立的容器選擇適當的名稱,以儲存 Bot 狀態。 在下列範例中,所建立的 Cosmos DB 容器將會命名為 “bot-storage”。
將下列資訊新增至組態檔。
appsettings.json
"CosmosDbEndpoint": "<your-CosmosDb-URI>",
"CosmosDbAuthKey": "<your-primary-key>",
"CosmosDbDatabaseId": "<your-database-id>",
"CosmosDbContainerId": "bot-storage"
安裝 Cosmos DB 套件
請確定您有 Cosmos DB 所需的套件。
安裝 Microsoft.Bot.Builder.Azure NuGet 套件。 如需使用 NuGet 的詳細資訊,請參閱使用 NuGet 封裝管理員 在 Visual Studio 中安裝和管理套件。
Cosmos DB 實作
注意
4.6 版引進了新的 Cosmos DB 記憶體提供者、 Cosmos DB 分割記憶體 類別,以及原始 Cosmos DB 儲存 類別已被取代。 使用 Cosmos DB 記憶體 建立的容器可以搭配 Cosmos DB 分割記憶體使用。 如需詳細資訊,請參閱 Azure Cosmos DB 中的數據分割。
不同於舊版 Cosmos DB 記憶體,Cosmos DB 分割記憶體不會自動在 Cosmos DB 帳戶內建立資料庫。 您必須 手動建立新的資料庫,但請略過手動建立容器,因為 CosmosDbPartitionedStorage 會為您建立容器。
下列範例程式代碼會使用與 上述記憶體記憶體 範例相同的 Bot 程式代碼來執行,但此處所列的例外狀況除外。 下列代碼段顯示 『myStorage』 的 Cosmos DB 記憶體實作,以取代本機記憶體記憶體記憶體。
您必須先更新Startup.cs以參考 Bot 建立器 Azure 連結庫:
using Microsoft.Bot.Builder.Azure;
接下來,在 ConfigureServices
Startup.cs 的方法中,建立 CosmosDbPartitionedStorage
物件。 這會透過相依性插入傳遞至建 EchoBot
構函式。
// 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,
}));
在 EchoBot.cs 將 _myStorage
變數宣告 private static readonly MemoryStorage _myStorage = new MemoryStorage();
變更為下列專案:
// variable used to save user input to CosmosDb Storage.
private readonly IStorage _myStorage;
然後將 物件傳入 IStorage
建 EchoBot
構函式:
public EchoBot(IStorage storage)
{
if (storage is null) throw new ArgumentNullException();
_myStorage = storage;
}
啟動 Cosmos DB Bot
在本機執行 Bot。
使用 Bot Framework 模擬器測試 Cosmos DB Bot
現在啟動 Bot Framework 模擬器,並連線到您的 Bot:
- 在 [模擬器歡迎使用] 索引標籤中選取 [建立新的 Bot 組態] 連結。
- 填入欄位以連線到您的 Bot,指定您啟動 Bot 時所顯示網頁上的資訊。
與您的 Cosmos DB Bot 互動
將訊息傳送至 Bot,Bot 會列出其收到的訊息。
檢視 Cosmos DB 數據
執行 Bot 並儲存資訊之後,您可以在 [資料總管] 索引卷標下檢視儲存在 [Azure 入口網站 中的數據。
使用 Blob 記憶體
Azure Blob 儲存體是 Microsoft 針對雲端推出的物件儲存體解決方案。 Blob 儲存體已針對儲存大量非結構化資料 (如文字或二進位資料) 進行最佳化。 本節說明如何建立 Azure Blob 記憶體帳戶和容器,以及如何從 Bot 參考 Blob 記憶體容器。
如需 Blob 記憶體的詳細資訊,請參閱 什麼是 Azure Blob 記憶體?
建立 Blob 記憶體帳戶
若要在 Bot 中使用 Blob 記憶體,您需要先設定一些專案,才能進入程式代碼。
在 Azure 入口網站中,選取 [所有服務]。
在 [所有服務] 頁面的 [精選] 區段中,選取 [儲存體帳戶]。
在 [ 記憶體帳戶] 頁面中,選取 [ 新增]。
在 [訂用帳戶] 欄位中,選取要在其中建立儲存體帳戶的訂用帳戶。
在 [ 資源群組] 字段中,選取現有的資源群組 或選取 [新建],然後輸入新資源群組的名稱。
在 [儲存體帳戶名稱] 欄位中,輸入帳戶的名稱。 請注意下列指導方針:
- 名稱在整個 Azure 中必須是唯一的。
- 名稱長度必須介於 3 到 24 個字元之間。
- 名稱只能包含數字和小寫字母。
在 [位置] 欄位中,選取儲存體帳戶的位置,或使用預設位置。
針對其餘的設定,請設定下列各項:
在 [建立記憶體帳戶] 頁面的 [專案詳細數據] 區段中,選取訂用帳戶和資源群組所需的值。
在 [建立記憶體帳戶] 頁面的 [實例詳細數據] 區段中,輸入記憶體帳戶名稱,然後選取 [位置]、[帳戶種類] 和 [複寫] 的值。
選取 [檢閱 + 建立] 以檢閱儲存體帳戶設定。
驗證後,選取 [建立]。
建立 Blob 記憶體容器
建立 Blob 記憶體帳戶之後,請開啟它,然後:
選擇[儲存體總管[預覽] 。
然後以滑鼠右鍵按兩下 [BLOB 容器]
從下拉式清單中選取 [建立 Blob 容器 ]。
在 [新增容器] 表單中輸入名稱。 您將使用此名稱做為「Blob 容器名稱」的值,以提供 Blob 記憶體帳戶的存取權。 請注意下列指導方針:
- 此名稱只能包含小寫字母、數位和連字元。
- 此名稱的開頭必須是字母或數位。
- 每個連字元前面必須加上,後面接著有效的非連字元字元。
- 名稱長度必須為 3 到 63 個字元。
新增 Blob 記憶體組態資訊
尋找您需要為 Bot 設定 Blob 記憶體所需的 Blob 記憶體密鑰,如下所示:
- 在 Azure 入口網站 中,開啟您的 Blob 記憶體帳戶,然後在 [設定] 區段中選取 [存取密鑰]。
- 若要將 Bot 設定為存取 Blob 記憶體帳戶,請使用連接字串作為 blob 連接字串 的值。
將下列資訊新增至組態檔。
appsettings.json
"BlobConnectionString": "<your-blob-connection-string>",
"BlobContainerName": "<your-blob-container-name>",
安裝 Blob 記憶體套件
如果先前未安裝,請安裝下列套件。
安裝 Microsoft.Bot.Builder.Azure.Blobs NuGet 套件。 如需使用 NuGet 的詳細資訊,請參閱使用 NuGet 封裝管理員 在 Visual Studio 中安裝和管理套件。
Blob 記憶體實作
Blob 記憶體 是用來儲存 Bot 狀態。
注意
自 4.10 版起, Microsoft.Bot.Builder.Azure.AzureBlobStorage
已被取代。 在位置使用新的 Microsoft.Bot.Builder.Azure.Blobs.BlobsStorage
。
下列範例程式代碼會使用與 上述記憶體記憶體 範例相同的 Bot 程式代碼來執行,但此處所列的例外狀況除外。
下列代碼段顯示 『myStorage』 的 Blob 記憶體實作,以取代本機記憶體記憶體記憶體。
您必須先更新Startup.cs以參考 Bot 建立器 Azure Blob 連結庫:
Startup.cs
using Microsoft.Bot.Builder.Azure.Blobs;
接下來,在 ConfigureServices
Startup.cs 的方法中,建立 BlobsStorage
對象,傳入 來自appsettings.json
的值。 這會透過相依性插入傳遞至建 EchoBot
構函式。
//Use Azure Blob storage, instead of in-memory storage.
services.AddSingleton<IStorage>(
new BlobsStorage(
Configuration.GetValue<string>("BlobConnectionString"),
Configuration.GetValue<string>("BlobContainerName")
));
現在,您必須先更新EchoBot.cs以參考 Bot 建立器 Azure Blob 連結庫:
EchoBot.cs
using Microsoft.Bot.Builder.Azure.Blobs;
接下來,請移除或批注化建立 MemoryStorage 變數 'private static readonly MemoryStorage _myStorage = new MemoryStorage():' 的程式代碼行,並建立將用來將使用者輸入儲存至 Blob 記憶體的新變數。
EchoBot.cs
// variable used to save user input to CosmosDb Storage.
private readonly IStorage _myStorage;
然後將 物件傳入 IStorage
建 EchoBot
構函式:
public EchoBot(IStorage storage)
{
if (storage is null) throw new ArgumentNullException();
_myStorage = storage;
}
一旦記憶體設定為指向 Blob 記憶體帳戶,Bot 程式代碼現在將會儲存及擷取 Blob 記憶體中的數據。
一旦記憶體設定為指向 Blob 記憶體帳戶,Bot 程式代碼現在將會儲存及擷取 Blob 記憶體中的數據。
啟動 Blob 記憶體 Bot
在本機執行 Bot。
啟動模擬器並連線 Blob 記憶體 Bot
接下來,啟動模擬器,然後在模擬器中聯機到您的 Bot:
- 選取模擬器 [歡迎使用] 索引標籤中的 [ 建立新的 Bot 組態 ] 連結。
- 填入欄位以連線到您的 Bot,指定您啟動 Bot 時所顯示網頁上的資訊。
與您的 Blob 記憶體 Bot 互動
將訊息傳送至 Bot,Bot 會列出其收到的訊息。
檢視 Blob 記憶體數據
執行 Bot 並儲存資訊之後,我們可以在 Azure 入口網站 的 [儲存體總管] 索引標籤下檢視它。
Blob 文字記錄記憶體
Azure Blob 文字記錄記憶體提供特殊的記憶體選項,可讓您輕鬆地以錄製文字記錄的形式儲存和擷取使用者交談。 Azure Blob 文字記錄記憶體很適合用來自動擷取使用者輸入,以在對 Bot 效能進行偵錯時進行檢查。
注意
Python 目前 不支援 Azure Blob 文字記錄記憶體。 雖然 JavaScript 支援 Blob 文字記錄記憶體,但下列指示僅適用於 C#。
設定 Blob 文字記錄記憶體容器
Azure Blob 文字記錄記憶體可以使用遵循上述<
- 開啟您的 Azure Blob 記憶體帳戶。
- 選取 [儲存體總管]。
- 以滑鼠右鍵按兩下 [BLOB 容器 ],然後選取 [ 建立 Blob 容器]。
- 輸入文字記錄容器的名稱,然後選取 [ 確定]。 (我們輸入 mybottranscripts)
Blob 文字記錄記憶體實作
下列程式代碼會將文字記錄記憶體指標 _myTranscripts
連線到新的 Azure Blob 文字記錄記憶體帳戶。 若要使用新的容器名稱 <your-blob-transcript-container-name> 建立此連結,它會在 Blob 記憶體中建立新的容器來保存您的文字記錄檔。
Blob 文字記錄記憶體 是設計來儲存 Bot 文字記錄。
注意
自 4.10 版起, Microsoft.Bot.Builder.Azure.AzureBlobTranscriptStore
已被取代。 在位置使用新的 Microsoft.Bot.Builder.Azure.Blobs.BlobsTranscriptStore
。
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>");
...
}
將使用者交談儲存在 Azure Blob 文字記錄中
在 Blob 容器可供儲存文字記錄之後,您可以開始保留使用者與 Bot 的交談。 這些交談稍後可用來作為偵錯工具,以查看使用者如何與您的 Bot 互動。 每個模擬器 重新啟動交談 都會起始新文字記錄交談清單的建立。 下列程式代碼會在預存的文字記錄檔中保留使用者交談輸入。
- 目前的文字記錄會使用
LogActivityAsync
儲存。 - 已儲存的文字記錄是使用
ListTranscriptsAsync
來擷取。 在此範例程式代碼中,每個預存文字記錄的標識符都會儲存到名為 「storedTranscripts」 的清單。 此清單稍後會用來管理我們保留的預存 Blob 文字記錄數目。
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);
...
}
管理儲存的 Blob 文字記錄
雖然預存的文字記錄可作為偵錯工具,但隨著時間推移,儲存的文字記錄數目可能會比您關心的要保留還要大。 下面包含的其他程式代碼會使用 DeleteTranscriptAsync
從 Blob 文字記錄存放區移除最後三個擷取的文字記錄專案。
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);
}
}
}
...
}
如需 類別的詳細資訊,請參閱 Azure Blob 文字記錄記憶體。
其他資訊
使用 eTag 管理並行
在我們的 Bot 程式代碼範例中,我們會將 每個 IStoreItem
的屬性設定eTag
為 *
。 eTag
存放區物件的 (實體卷標) 成員會在 Cosmos DB 內用來管理並行。 eTag
會告知您的資料庫,如果 Bot 的另一個實例已變更 Bot 所寫入之相同記憶體中的物件,該怎麼做。
上次寫入獲勝 - 允許覆寫
星號的屬性值 (*
) 表示最後一個eTag
寫入器獲勝。 建立新的資料存放區時,您可以設定 eTag
屬性來 *
指出您先前尚未儲存要寫入的數據,或您想要最後一個寫入器覆寫任何先前儲存的屬性。 如果 Bot 的並行存取不是問題,請針對您正在撰寫的任何資料將 屬性*
設定eTag
為 ,以啟用覆寫。
維護並行並防止覆寫
將數據儲存至 Cosmos DB 時,如果您想要防止對 屬性的並行存取,並避免覆寫來自另一個 Bot 實例的變更,請使用 以外的值*
eTag
。 Bot 會在嘗試儲存狀態數據,且 eTag
與記憶體中的 值不同eTag
時,收到訊息etag conflict key=
的錯誤回應。
根據預設,Cosmos DB 存放區會在每次 Bot 寫入該專案時檢查 eTag
記憶體物件的 屬性是否相等,然後在每次寫入之後,將其更新為新的唯一值。 eTag
如果寫入上的 屬性不符合eTag
記憶體中的 ,表示另一個 Bot 或線程已變更數據。
例如,假設您想要讓 Bot 編輯已儲存的附註,但不希望 Bot 覆寫另一個 Bot 實例所做的變更。 如果 Bot 的另一個實體已進行編輯,您希望使用者以最新的更新來編輯版本。
首先,建立實作 的 IStoreItem
類別。
EchoBot.cs
public class Note : IStoreItem
{
public string Name { get; set; }
public string Contents { get; set; }
public string ETag { get; set; }
}
接下來,建立記憶體物件來建立初始附注,並將物件新增至您的存放區。
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);
然後,稍後存取並更新附註,並 eTag
保留您從市集讀取的附註。
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);
}
如果您在撰寫變更之前已在存放區中更新附註,呼叫 Write
將會擲回例外狀況。
若要維護並行,請一律從記憶體讀取屬性,然後修改您讀取的屬性,以便 eTag
維護 。 如果您從存放區讀取用戶數據,回應會包含 eTag 屬性。 如果您變更數據並將更新的數據寫入至存放區,您的要求應該包含 eTag 屬性,指定與先前讀取相同的值。 不過,將物件設定 eTag
為 *
來寫入,將允許寫入覆寫任何其他變更。
下一步
既然您已瞭解如何直接從記憶體讀取和寫入,讓我們看看如何使用狀態管理員為您執行此作業。