如何搭配 C++ 使用 Azure 資料表記憶體和適用於資料表的 Azure Cosmos DB

適用於: Table

提示

本文的內容適用於 Azure 資料表記憶體和適用於資料表的 Azure Cosmos DB。 Table 的 API 是數據表記憶體的進階供應專案,可提供輸送量優化的數據表、全域散發和自動次要索引。

本指南說明使用 Azure 數據表記憶體服務或適用於數據表的 Azure Cosmos DB 的常見案例。 這些範例是以 C++ 撰寫,並使用適用於 C++ 的 Azure 儲存體 客戶端連結庫。 本文涵蓋下列案例:

  • 建立和刪除數據表
  • 使用數據表實體

注意

本指南的目標是適用於 C++ 1.0.0 版和更新版本的 Azure 儲存體 客戶端連結庫。 建議的版本 儲存體 客戶端連結庫 2.2.0,可使用 NuGetGitHub

建立帳戶

建立 Azure 服務帳戶

您可以使用 Azure 資料表記憶體或 Azure Cosmos DB 來處理資料表。 若要深入瞭解這兩個服務中的數據表供應專案之間的差異,請參閱 API for Table 概觀。 您必須為要使用的服務建立帳戶。 下列各節說明如何建立 Azure 數據表記憶體和 Azure Cosmos DB 帳戶,不過您只能使用其中一個帳戶。

建立 Azure 儲存體帳戶

建立 Azure 記憶體帳戶最簡單的方式是使用 Azure 入口網站。 若要深入了解,請參閱 建立儲存體帳戶

您也可以使用 Azure PowerShellAzure CLI 來建立 Azure 記憶體帳戶。

如果您目前不想建立記憶體帳戶,您也可以使用 Azure 儲存體 模擬器,在本機環境中執行及測試程序代碼。 如需詳細資訊,請參閱使用 Azure 儲存體模擬器進行開發和測試

建立適用於數據表帳戶的 Azure Cosmos DB

如需建立適用於數據表帳戶的 Azure Cosmos DB 的指示,請參閱 建立資料庫帳戶

建立 C++ 應用程式

在本指南中,您會使用來自 C++ 應用程式的記憶體功能。 若要這樣做,請安裝適用於 C++ 的 Azure 儲存體 客戶端連結庫。

若要安裝適用於 C++ 的 Azure 儲存體 客戶端連結庫,請使用下列方法:

  • Linux:遵循適用於 C++ 的 Azure 儲存體 客戶端連結庫中提供的指示:開始使用 Linux 頁面。
  • Windows: 在 Windows 上,請使用 vcpkg 作為相依性管理員。 請遵循快速入門來初始化 vcpkg。 然後,使用下列命令安裝二進位檔:
.\vcpkg.exe install azure-storage-cpp

您可以在自述檔中找到如何建置原始程式碼並匯出至 Nuget 的指南。

設定數據表用戶端連結庫的存取權

若要使用 Azure 記憶體 API 來存取資料表,請將下列 include 語句新增至 C++ 檔案頂端:

#include <was/storage_account.h>
#include <was/table.h>

Azure 儲存體 用戶端或 Azure Cosmos DB 用戶端會使用 連接字串 來儲存端點和認證來存取數據管理服務。 當您執行用戶端應用程式時,必須以適當的格式提供記憶體 連接字串 或 Azure Cosmos DB 連接字串。

設定 Azure 儲存體連接字串

此範例示範如何宣告靜態字段來保存 Azure 儲存體 連接字串:

// Define the Storage connection string with your values.
const utility::string_t storage_connection_string(U("DefaultEndpointsProtocol=https;AccountName=<your_storage_account>;AccountKey=<your_storage_account_key>"));

使用 儲存體 帳戶<your_storage_account>的名稱。 針對 <your_storage_account_key>,請使用 Azure 入口網站 中所列 儲存體 帳戶的存取密鑰。 如需 儲存體 帳戶和存取金鑰的相關信息,請參閱建立記憶體帳戶

設定 Azure Cosmos DB 連接字串

此範例示範如何宣告靜態字段來保存 Azure Cosmos DB 連接字串:

// Define the Azure Cosmos DB connection string with your values.
const utility::string_t storage_connection_string(U("DefaultEndpointsProtocol=https;AccountName=<your_cosmos_db_account>;AccountKey=<your_cosmos_db_account_key>;TableEndpoint=<your_cosmos_db_endpoint>"));

針對使用 Azure Cosmos DB 帳戶 <your_cosmos_db_account>的名稱。 輸入您的主鍵。<your_cosmos_db_account_key> 輸入 Azure 入口網站 中所列的<your_cosmos_db_endpoint>端點。

若要在本機 Windows 計算機中測試您的應用程式,您可以使用隨 Azure SDK 一起安裝的 Azure 儲存體 模擬器。 儲存體 模擬器是一個公用程式,可模擬本機開發計算機上可用的 Azure Blob、佇列和數據表服務。 下列範例示範如何宣告靜態字段來保存本機記憶體仿真器 連接字串:

// Define the connection string with Azure Storage Emulator.
const utility::string_t storage_connection_string(U("UseDevelopmentStorage=true;"));  

若要啟動 Azure 儲存體 模擬器,請從 Windows 桌面選取 [開始] 按鈕或 Windows 鍵。 輸入並執行 Microsoft Azure 儲存體 模擬器。 如需詳細資訊,請參閱使用 Azure 儲存體模擬器進行開發和測試

擷取連接字串

您可以使用 cloud_storage_account 類別來代表儲存體帳戶資訊。 若要從記憶體 連接字串 擷取記憶體帳戶資訊,請使用 parse 方法。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

接下來,取得類別的 cloud_table_client 參考。 這個類別可讓您取得數據表記憶體服務內儲存之數據表和實體的參考物件。 下列程式代碼會使用您先前擷取的記憶體帳戶物件來建立 cloud_table_client 物件:

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

建立實體並新增至數據表

建立表格

物件 cloud_table_client 可讓您取得數據表和實體的參考物件。 下列程式代碼會 cloud_table_client 建立 物件,並用它來建立新的數據表。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);  

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Retrieve a reference to a table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Create the table if it doesn't exist.
table.create_if_not_exists();  

將實體新增至資料表

若要將實體新增至資料表,請建立新的 table_entity 物件,並將它傳遞至 table_operation::insert_entity。 下列程式代碼會使用客戶的名字作為數據列索引鍵,並將姓氏當做分割區索引鍵。 一起,實體的數據分割和數據列索引鍵可唯一識別數據表中的實體。 具有相同分割區索引鍵的實體可以比具有不同分割區索引鍵的實體更快查詢。 使用不同的分割區索引鍵可讓平行作業延展性更高。 如需詳細資訊,請參閱 Microsoft Azure 記憶體效能和延展性檢查清單

下列程式代碼會建立 新的實例 table_entity ,其中包含要儲存的一些客戶數據。 程式代碼接著會呼叫 table_operation::insert_entity 來建立 table_operation 物件,以將實體插入數據表,並將新的數據表實體與其產生關聯。 最後,程序代碼會在物件上cloud_table呼叫 execute 方法。 table_operation新的會將要求傳送至數據表服務,以將新的客戶實體插入數據表中people

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Retrieve a reference to a table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Create the table if it doesn't exist.
table.create_if_not_exists();

// Create a new customer entity.
azure::storage::table_entity customer1(U("Harp"), U("Walter"));

azure::storage::table_entity::properties_type& properties = customer1.properties();
properties.reserve(2);
properties[U("Email")] = azure::storage::entity_property(U("Walter@contoso.com"));

properties[U("Phone")] = azure::storage::entity_property(U("425-555-0101"));

// Create the table operation that inserts the customer entity.
azure::storage::table_operation insert_operation = azure::storage::table_operation::insert_entity(customer1);

// Execute the insert operation.
azure::storage::table_result insert_result = table.execute(insert_operation);

插入一批實體

您可以在一個寫入作業中,將一批實體插入數據表服務。 下列程式代碼會建立 物件,然後將三個 table_batch_operation 插入作業加入其中。 每個插入作業都是藉由建立新的實體對象、設定其值,然後在物件上table_batch_operation呼叫 insert 方法,以將實體與新的插入作業產生關聯。 然後,程式代碼會呼叫 cloud_table.execute 來執行作業。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Define a batch operation.
azure::storage::table_batch_operation batch_operation;

// Create a customer entity and add it to the table.
azure::storage::table_entity customer1(U("Smith"), U("Jeff"));

azure::storage::table_entity::properties_type& properties1 = customer1.properties();
properties1.reserve(2);
properties1[U("Email")] = azure::storage::entity_property(U("Jeff@contoso.com"));
properties1[U("Phone")] = azure::storage::entity_property(U("425-555-0104"));

// Create another customer entity and add it to the table.
azure::storage::table_entity customer2(U("Smith"), U("Ben"));

azure::storage::table_entity::properties_type& properties2 = customer2.properties();
properties2.reserve(2);
properties2[U("Email")] = azure::storage::entity_property(U("Ben@contoso.com"));
properties2[U("Phone")] = azure::storage::entity_property(U("425-555-0102"));

// Create a third customer entity to add to the table.
azure::storage::table_entity customer3(U("Smith"), U("Denise"));

azure::storage::table_entity::properties_type& properties3 = customer3.properties();
properties3.reserve(2);
properties3[U("Email")] = azure::storage::entity_property(U("Denise@contoso.com"));
properties3[U("Phone")] = azure::storage::entity_property(U("425-555-0103"));

// Add customer entities to the batch insert operation.
batch_operation.insert_or_replace_entity(customer1);
batch_operation.insert_or_replace_entity(customer2);
batch_operation.insert_or_replace_entity(customer3);

// Execute the batch operation.
std::vector<azure::storage::table_result> results = table.execute_batch(batch_operation);

批次作業需要注意的一些事項:

  • 您可以在單一批次中的任何組合中執行最多 100 insert個 、 deletemergereplaceinsert-or-mergeinsert-or-replace 作業。
  • 如果批次作業是批次中唯一的作業,則批次作業可以有擷取作業。
  • 單一批次作業中的所有實體都必須具有相同的數據分割索引鍵。
  • 批次作業僅限於 4 MB 的數據承載。

查詢和修改實體

擷取分割中的所有實體

若要查詢分割中所有實體的資料表,請使用 table_query 物件。 下列程式代碼範例會指定實體的篩選,其中 Smith 是分割區索引鍵。 本範例會將查詢結果中每個實體的欄位列印至主控台。

注意

Azure Cosmos DB 中的 C++ 目前不支援這些方法。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Construct the query operation for all customer entities where PartitionKey="Smith".
azure::storage::table_query query;

query.set_filter_string(azure::storage::table_query::generate_filter_condition(U("PartitionKey"), azure::storage::query_comparison_operator::equal, U("Smith")));

// Execute the query.
azure::storage::table_query_iterator it = table.execute_query(query);

// Print the fields for each customer.
azure::storage::table_query_iterator end_of_results;
for (; it != end_of_results; ++it)
{
    const azure::storage::table_entity::properties_type& properties = it->properties();

    std::wcout << U("PartitionKey: ") << it->partition_key() << U(", RowKey: ") << it->row_key()
        << U(", Property1: ") << properties.at(U("Email")).string_value()
        << U(", Property2: ") << properties.at(U("Phone")).string_value() << std::endl;
}  

此範例中的查詢會傳回符合篩選準則的所有實體。 如果您有大型數據表且需要經常下載數據表實體,建議您改為將數據儲存在 Azure 記憶體 Blob 中。

擷取分割中某範圍的實體

如果您不想查詢分割區中的所有實體,您可以指定範圍。 結合數據分割索引鍵篩選與數據列索引鍵篩選。 下列程式代碼範例會使用兩個篩選來取得數據分割 Smith 中的所有實體,其中數據列索引鍵 (名字) 開頭為字母早於 E 字母,然後列印查詢結果。

注意

Azure Cosmos DB 中的 C++ 目前不支援這些方法。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Create the table query.
azure::storage::table_query query;

query.set_filter_string(azure::storage::table_query::combine_filter_conditions(
    azure::storage::table_query::generate_filter_condition(U("PartitionKey"),
    azure::storage::query_comparison_operator::equal, U("Smith")),
    azure::storage::query_logical_operator::op_and,
    azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::less_than, U("E"))));

// Execute the query.
azure::storage::table_query_iterator it = table.execute_query(query);

// Loop through the results, displaying information about the entity.
azure::storage::table_query_iterator end_of_results;
for (; it != end_of_results; ++it)
{
    const azure::storage::table_entity::properties_type& properties = it->properties();

    std::wcout << U("PartitionKey: ") << it->partition_key() << U(", RowKey: ") << it->row_key()
        << U(", Property1: ") << properties.at(U("Email")).string_value()
        << U(", Property2: ") << properties.at(U("Phone")).string_value() << std::endl;
}  

擷取單一實體

您可以撰寫查詢來擷取單一特定實體。 下列程式代碼會使用 table_operation::retrieve_entity 來指定客戶 Jeff Smith。 這個方法只會傳回一個實體,而不是集合,而傳回的值在 中 table_result。 在查詢中同時指定數據分割和數據列索引鍵,是從數據表服務擷取單一實體最快的方式。

azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Retrieve the entity with partition key of "Smith" and row key of "Jeff".
azure::storage::table_operation retrieve_operation = azure::storage::table_operation::retrieve_entity(U("Smith"), U("Jeff"));
azure::storage::table_result retrieve_result = table.execute(retrieve_operation);

// Output the entity.
azure::storage::table_entity entity = retrieve_result.entity();
const azure::storage::table_entity::properties_type& properties = entity.properties();

std::wcout << U("PartitionKey: ") << entity.partition_key() << U(", RowKey: ") << entity.row_key()
    << U(", Property1: ") << properties.at(U("Email")).string_value()
    << U(", Property2: ") << properties.at(U("Phone")).string_value() << std::endl;

取代實體

若要取代實體,請從 Table 服務擷取它、修改實體物件,然後將變更儲存回數據表服務。 下列程式代碼會變更現有客戶的電話號碼和電子郵件位址。 此程式代碼會使用 table_operation::replace_entity,而不是呼叫 table_operation::insert_entity。 此方法會導致在伺服器上完全取代實體,除非伺服器上實體自擷取后已變更。 如果已變更,作業就會失敗。 此失敗可防止您的應用程式覆寫另一個元件在擷取和更新之間所做的變更。 此失敗的適當處理是再次擷取實體、變更、如果仍然有效,然後執行另一個 table_operation::replace_entity 作業。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Replace an entity.
azure::storage::table_entity entity_to_replace(U("Smith"), U("Jeff"));
azure::storage::table_entity::properties_type& properties_to_replace = entity_to_replace.properties();
properties_to_replace.reserve(2);

// Specify a new phone number.
properties_to_replace[U("Phone")] = azure::storage::entity_property(U("425-555-0106"));

// Specify a new email address.
properties_to_replace[U("Email")] = azure::storage::entity_property(U("JeffS@contoso.com"));

// Create an operation to replace the entity.
azure::storage::table_operation replace_operation = azure::storage::table_operation::replace_entity(entity_to_replace);

// Submit the operation to the Table service.
azure::storage::table_result replace_result = table.execute(replace_operation);

插入或取代實體

table_operation::replace_entity 如果實體自從伺服器擷取后已變更,作業就會失敗。 此外,您必須先從伺服器擷取實體,才能 table_operation::replace_entity 成功。 有時候,您不知道實體是否存在於伺服器上。 儲存在其中的目前值無關緊要,因為您的更新應該全部覆寫。 若要完成此結果,請使用 table_operation::insert_or_replace_entity 作業。 如果實體不存在,此作業就會插入該實體。 如果實體存在,則此作業會取代實體。 在下列程式代碼範例中,仍會擷取的客戶實體 Jeff Smith ,但接著會使用 table_operation::insert_or_replace_entity將它儲存回伺服器。 在擷取和更新作業之間對實體所做的任何更新都會遭到覆寫。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Insert or replace an entity.
azure::storage::table_entity entity_to_insert_or_replace(U("Smith"), U("Jeff"));
azure::storage::table_entity::properties_type& properties_to_insert_or_replace = entity_to_insert_or_replace.properties();

properties_to_insert_or_replace.reserve(2);

// Specify a phone number.
properties_to_insert_or_replace[U("Phone")] = azure::storage::entity_property(U("425-555-0107"));

// Specify an email address.
properties_to_insert_or_replace[U("Email")] = azure::storage::entity_property(U("Jeffsm@contoso.com"));

// Create an operation to insert or replace the entity.
azure::storage::table_operation insert_or_replace_operation = azure::storage::table_operation::insert_or_replace_entity(entity_to_insert_or_replace);

// Submit the operation to the Table service.
azure::storage::table_result insert_or_replace_result = table.execute(insert_or_replace_operation);

查詢實體屬性的子集

數據表的查詢只能從實體擷取幾個屬性。 下列程式代碼中的查詢會使用 table_query::set_select_columns 方法,只傳回數據表中實體的電子郵件位址。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Define the query, and select only the Email property.
azure::storage::table_query query;
std::vector<utility::string_t> columns;

columns.push_back(U("Email"));
query.set_select_columns(columns);

// Execute the query.
azure::storage::table_query_iterator it = table.execute_query(query);

// Display the results.
azure::storage::table_query_iterator end_of_results;
for (; it != end_of_results; ++it)
{
    std::wcout << U("PartitionKey: ") << it->partition_key() << U(", RowKey: ") << it->row_key();

    const azure::storage::table_entity::properties_type& properties = it->properties();
    for (auto prop_it = properties.begin(); prop_it != properties.end(); ++prop_it)
    {
        std::wcout << ", " << prop_it->first << ": " << prop_it->second.str();
    }

    std::wcout << std::endl;
}

注意

從實體查詢幾個屬性比擷取所有屬性更有效率的作業。

刪除內容

刪除實體

您可以在擷取實體之後刪除實體。 擷取實體之後,請使用要刪除的實體呼叫 table_operation::delete_entity 。 接著呼叫 cloud_table.execute 方法。 下列程式代碼會擷取和刪除具有 數據分割索引鍵 Smith 的 實體,以及的數據列索引鍵 Jeff

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Create an operation to retrieve the entity with partition key of "Smith" and row key of "Jeff".
azure::storage::table_operation retrieve_operation = azure::storage::table_operation::retrieve_entity(U("Smith"), U("Jeff"));
azure::storage::table_result retrieve_result = table.execute(retrieve_operation);

// Create an operation to delete the entity.
azure::storage::table_operation delete_operation = azure::storage::table_operation::delete_entity(retrieve_result.entity());

// Submit the delete operation to the Table service.
azure::storage::table_result delete_result = table.execute(delete_operation);  

刪除資料表

最後,下列程式代碼範例會從記憶體帳戶中刪除數據表。 刪除的數據表無法在刪除之後重新建立一段時間。

// Retrieve the storage account from the connection string.
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(storage_connection_string);

// Create the table client.
azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client();

// Create a cloud table object for the table.
azure::storage::cloud_table table = table_client.get_table_reference(U("people"));

// Delete the table if it exists
if (table.delete_table_if_exists())
{
    std::cout << "Table deleted!";
}
else
{
    std::cout << "Table didn't exist";
}

疑難排解

針對 Visual Studio Community Edition,如果您的專案因為 include 檔案storage_account.h 和 table.h 而收到建置錯誤,請移除 /permissive- 編譯程序參數:

  1. 方案總管 中,以滑鼠右鍵按下您的專案,然後選取 [屬性]。
  2. 在 [ 屬性頁] 對話框中,依序展開 [組態屬性]、[ C/C++],然後選取 [ 語言]。
  3. 將 [一致性] 模式設定[否]。

下一步

Microsoft Azure 儲存體總管 是一個免費的獨立應用程式,可讓您在 Windows、MacOS 和 Linux 上以視覺化方式處理 Azure 儲存體資料。

請遵循下列連結以深入瞭解 Azure Cosmos DB 中的數據表 Azure 儲存體 和 API: