Использование хранилища таблиц Azure и Azure Cosmos DB для таблицы с C++
Область применения: Таблица
Совет
Содержимое этой статьи относится к хранилищу таблиц Azure и Azure Cosmos DB для таблицы. API для таблицы — это предложение уровня "Премиум" для хранилища таблиц, которое предлагает оптимизированные для пропускной способности таблицы, глобальное распределение и автоматические вторичные индексы.
В этом руководстве показаны распространенные сценарии с помощью службы хранилища таблиц Azure или Azure Cosmos DB для таблицы. Примеры написаны на C++ и используют клиентскую библиотеку хранилища Azure для C++. В этой статье рассмотрены следующие сценарии:
- Создание и удаление таблицы.
- Работа с сущностями таблиц.
Примечание.
Данное руководство предназначено для клиентской библиотеки хранилища Azure для С++ версии 1.0.0 и выше. Рекомендуемая версия клиентской библиотеки хранилища — 2.2.0. Она доступна на сайте NuGet или GitHub.
Создание учетных записей
Создание учетной записи службы Azure
Вы можете работать с таблицами, используя хранилище таблиц Azure или Azure Cosmos DB. Дополнительные сведения о различиях между предложениями таблиц в этих двух службах см. в обзоре API для таблиц. Для службы, которую вы планируете использовать, потребуется создать учетную запись. В следующих разделах показано, как создать и хранилище таблиц Azure, и учетную запись Azure Cosmos DB, однако можно использовать что-то одно.
Создание учетной записи службы хранилища Azure
Самый простой способ создать учетную запись хранения Azure — воспользоваться порталом Azure. Чтобы узнать больше, см. раздел Создание учетной записи хранилища.
Учетную запись хранения Azure можно создать также с помощью Azure PowerShell или Azure CLI.
Если вы не хотите сейчас создавать учетную запись хранения, код можно запустить и протестировать в локальной среде с помощью эмулятора хранения Azure. Дополнительные сведения см. в статье Использование Эмулятора службы хранилища Azure для разработки и тестирования.
Создание учетной записи Azure Cosmos DB для таблицы
Инструкции по созданию учетной записи Azure Cosmos DB для таблицы см. в статье "Создание учетной записи базы данных".
Создание приложения на C++
В этом руководстве вы используете функции хранилища из приложения C++. Для этого установите клиентскую библиотеку службы хранилища Azure для C++.
Чтобы установить клиентскую библиотеку службы хранилища для C++, используйте следующие методы:
- Linux. Следуйте инструкциям, указанным в файле README клиентской библиотеки службы хранилища Azure для C++ на странице для начала работы в Linux.
- Windows: в Windows в качестве диспетчера зависимостей используйте vcpkg. Следуйте инструкциям из этого краткого руководства, чтобы инициализировать vcpkg. Затем, чтобы установить библиотеку, используйте следующую команду:
.\vcpkg.exe install azure-storage-cpp
Руководство по созданию исходного кода и экспорту в Nuget можно просмотреть в файле README.
Настройка доступа к клиентской библиотеке таблиц
Чтобы использовать API-интерфейсы хранилища Azure, добавьте следующие инструкции 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. Сведения об учетных записях хранения и ключах доступа см. в статье Create a storage account (Создание учетной записи хранения).
Настройка строки подключения к 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, устанавливаемый с пакетом Azure SDK. Эмулятор службы хранилища — это служебная программа, моделирующая службы больших двоичных объектов, очередей и таблиц, которые доступны в Azure на локальном компьютере разработки. В следующем примере показано, как объявить статическое поле для размещения строки подключения для эмулятора локального хранилища:
// 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
для вставки сущности в таблицу, и связывает с ним новую сущность таблицы. В завершение код вызывает метод execute
для объекта cloud_table
. Новый 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
, а затем добавляет в него три операции вставки. Каждая операция вставки добавляется путем создания объекта сущности, установки его значений и последующего вызова метода insert
для объекта table_batch_operation
, чтобы связать сущность с новой операцией вставки. Затем код вызывает 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
,delete
,merge
,replace
,insert-or-merge
иinsert-or-replace
в любых сочетаниях. - Пакетная операция может содержать операцию извлечения, если она является единственной в пакете.
- У всех сущностей в одной пакетной операции должен быть одинаковый ключ раздела.
- Максимальный объем полезных данных пакетной операции составляет 4 МБ.
Запросы к сущностям и их изменение
Получение всех сущностей в разделе
Чтобы запросить все сущности из таблицы, используйте объект table_query
. Следующий пример кода задает фильтр для сущностей с ключом раздела Smith
. Этот пример выводит на консоль поля каждой сущности в результатах запроса.
Примечание.
Эти методы сейчас не поддерживаются для C++ в базе данных Azure Cosmos DB.
// 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;
}
В этом примере запрос возвращает все сущности, соответствующие условиям фильтра. При наличии больших таблиц и необходимости часто загружать сущности таблицы мы рекомендуем хранить данные в хранилище BLOB-объектов Azure.
Получение диапазона сущностей в разделе
Если вы не хотите запрашивать все сущности в разделе, можно указать диапазон. Объедините фильтр ключей секций с фильтром ключей строк. В следующем примере кода используются два фильтра для получения всех сущностей в разделе Smith
, где ключ строки (имя) начинается с буквы алфавита, предшествующей E
, после чего результаты запроса выводятся в консоль.
Примечание.
Эти методы сейчас не поддерживаются для C++ в базе данных Azure Cosmos DB.
// 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_operation::insert_entity
этот код использует table_operation::replace_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: если сборка проекта завершается ошибкой из-за включаемых файлов storage_account.h и table.h, удалите параметр компилятора /permissive-:
- В обозревателе решений щелкните проект правой кнопкой мыши и выберите Свойства.
- В диалоговом окне Страницы свойств разверните узел Свойства конфигурации, затем разверните C/C++ и выберите Язык.
- Для параметра Режим совместимости установите значение Нет.
Следующие шаги
Обозреватель хранилищ Microsoft Azure — это бесплатное автономное приложение от корпорации Майкрософт, позволяющее визуализировать данные из службы хранилища Azure на платформе Windows, macOS и Linux.
Чтобы узнать больше о служба хранилища Azure и API для таблиц в Azure Cosmos DB, выполните следующие ссылки: