Como usar o armazenamento de Tabela do Azure e o Azure Cosmos DB para Tabela com C++

APLICA-SE A: Tabela

Gorjeta

O conteúdo deste artigo aplica-se ao armazenamento de Tabela do Azure e ao Azure Cosmos DB para Tabela. A API for Table é uma oferta premium para armazenamento de tabelas que oferece tabelas otimizadas para taxa de transferência, distribuição global e índices secundários automáticos.

Este guia mostra cenários comuns usando o serviço de armazenamento de Tabela do Azure ou o Azure Cosmos DB for Table. Os exemplos são escritos no C++ e utilizam a Biblioteca de Cliente de Armazenamento do Microsoft Azure para C++. Este artigo aborda os seguintes cenários:

  • Criar e excluir uma tabela
  • Trabalhar com entidades de tabela

Nota

Este guia destina-se à Biblioteca de Clientes de Armazenamento do Microsoft Azure para C++ versão 1.0.0 e acima. A versão recomendada é a Storage Client Library 2.2.0, que está disponível usando NuGet ou GitHub.

Criar contas

Criar uma conta de serviço do Azure

Você pode trabalhar com tabelas usando o armazenamento de tabela do Azure ou o Azure Cosmos DB. Para saber mais sobre as diferenças entre as ofertas de tabela nesses dois serviços, consulte a Visão geral da API para tabela. Terá de criar uma conta para o serviço que quer utilizar. As seções a seguir mostram como criar o armazenamento de tabela do Azure e a conta do Azure Cosmos DB, no entanto, você pode usar apenas um deles.

Criar uma conta de armazenamento do Azure

A maneira mais fácil de criar uma conta de armazenamento do Azure é usando o portal do Azure. Para saber mais, veja Criar uma conta de armazenamento.

Também pode criar uma conta de armazenamento do Azure com o Azure PowerShell ou a CLI do Azure.

Se preferir não criar uma conta de armazenamento neste momento, você também pode usar o Emulador de Armazenamento do Azure para executar e testar seu código em um ambiente local. Para obter mais informações, consulte Usar o emulador de armazenamento do Azure para desenvolvimento e teste.

Criar uma conta do Azure Cosmos DB para Tabela

Para obter instruções sobre como criar uma conta do Azure Cosmos DB for Table, consulte Criar uma conta de banco de dados.

Criar uma aplicação C++

Neste guia, você usa recursos de armazenamento de um aplicativo C++. Para fazer isso, instale a Biblioteca de Cliente de Armazenamento do Azure para C++.

Para instalar a Biblioteca de Cliente de Armazenamento do Azure para C++, use os seguintes métodos:

.\vcpkg.exe install azure-storage-cpp

Você pode encontrar um guia sobre como criar o código-fonte e exportar para o Nuget no arquivo LEIA-ME .

Configurar o acesso à biblioteca de cliente de tabela

Para usar as APIs de armazenamento do Azure para acessar tabelas, adicione as seguintes include instruções à parte superior do arquivo C++:

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

Um cliente de Armazenamento do Azure ou cliente do Azure Cosmos DB usa uma cadeia de conexão para armazenar pontos de extremidade e credenciais para acessar serviços de gerenciamento de dados. Ao executar um aplicativo cliente, você deve fornecer a cadeia de conexão de armazenamento ou a cadeia de conexão do Azure Cosmos DB no formato apropriado.

Configurar uma cadeia de ligação do Armazenamento do Microsoft Azure

Este exemplo mostra como declarar um campo estático para manter a cadeia de conexão do Armazenamento do 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>"));

Use o nome da sua conta de armazenamento para <your_storage_account>. Para <your_storage_account_key>, use a chave de acesso para a conta de armazenamento listada no portal do Azure. Para obter informações sobre contas de armazenamento e chaves de acesso, consulte Criar uma conta de armazenamento.

Configurar uma cadeia de ligação Azure Cosmos DB

Este exemplo mostra como declarar um campo estático para manter a cadeia de conexão do 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>"));

Use o nome da sua conta do Azure Cosmos DB para <your_cosmos_db_account>. Introduza a sua chave primária para <your_cosmos_db_account_key>. Insira o ponto de extremidade listado no portal do Azure para <your_cosmos_db_endpoint>.

Para testar seu aplicativo em seu computador local baseado no Windows, você pode usar o Emulador de Armazenamento do Azure instalado com o SDK do Azure. O Emulador de Armazenamento é um utilitário que simula os serviços de Blob, Fila e Tabela do Azure disponíveis em sua máquina de desenvolvimento local. O exemplo a seguir mostra como declarar um campo estático para manter a cadeia de conexão no emulador de armazenamento local:

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

Para iniciar o Emulador de Armazenamento do Azure, na área de trabalho do Windows, selecione o botão Iniciar ou a tecla Windows. Insira e execute o Emulador de Armazenamento do Microsoft Azure. Para obter mais informações, consulte Usar o emulador de armazenamento do Azure para desenvolvimento e teste.

Obter a cadeia de ligação

Você pode usar a classe para representar as informações da cloud_storage_account sua conta de armazenamento. Para recuperar as informações da conta de armazenamento da cadeia de conexão de armazenamento, use o parse método.

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

Em seguida, obtenha uma referência a uma cloud_table_client classe. Essa classe permite obter objetos de referência para tabelas e entidades armazenadas no serviço de armazenamento de tabela. O código a seguir cria um cloud_table_client objeto usando o objeto de conta de armazenamento recuperado anteriormente:

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

Criar e adicionar entidades a uma tabela

Criar uma tabela

Um cloud_table_client objeto permite obter objetos de referência para tabelas e entidades. O código a seguir cria um cloud_table_client objeto e o usa para criar uma nova tabela.

// 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();  

Adicionar uma entidade a uma tabela

Para adicionar uma entidade a uma tabela, crie um novo table_entity objeto e passe-o para table_operation::insert_entity. O código seguinte utiliza o nome próprio do cliente como a chave da fila e o apelido como a chave de partição. Em conjunto, a chave da fila e a partição da entidade identificam de forma exclusiva a entidade na tabela. As entidades com a mesma chave de partição podem ser consultadas mais rapidamente do que as entidades com chaves de partição diferentes. O uso de diversas chaves de partição permite uma maior escalabilidade de operação paralela. Para obter mais informações, consulte a Lista de Verificação de Desempenho e Escalabilidade do Armazenamento do Microsoft Azure.

O código a seguir cria uma nova instância de com alguns dados do table_entity cliente para armazenar. O código em seguida chama table_operation::insert_entity para criar um table_operation objeto para inserir uma entidade em uma tabela e associa a nova entidade de tabela a ela. Finalmente, o código chama o execute método no cloud_table objeto. O novo table_operation envia uma solicitação ao serviço Tabela para inserir a nova entidade do cliente na people tabela.

// 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);

Inserir um lote de entidades

Pode inserir um lote de entidades no serviço Tabela numa operação de escrita. O código a seguir cria um table_batch_operation objeto e, em seguida, adiciona três operações de inserção a ele. Cada operação de inserção é adicionada criando um novo objeto de entidade, definindo seus valores e, em seguida, chamando o inserttable_batch_operation método no objeto para associar a entidade a uma nova operação de inserção. Em seguida, o código chama cloud_table.execute para executar a operação.

// 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);

Algumas coisas a salientar nas operações de lote:

  • Você pode fazer até 100 insert, delete, , mergereplaceinsert-or-merge, e insert-or-replace operações em qualquer combinação em um único lote.
  • Uma operação em lote pode ter uma operação de recuperação, se for a única operação no lote.
  • Todas as entidades numa única operação em lote têm de ter a mesma chave de partição.
  • Uma operação em lote está limitada a um payload de dados de 4 MB.

Consultar e modificar entidades

Obter todas as entidades numa partição

Para consultar uma tabela para todas as entidades em uma partição, use um table_query objeto. O exemplo de código a seguir especifica um filtro para entidades onde Smith é a chave de partição. Este exemplo imprime os campos de cada entidade nos resultados da consulta para a consola.

Nota

Estes métodos não são atualmente suportados para C++ no 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;
}  

A consulta neste exemplo retorna todas as entidades que correspondem aos critérios de filtro. Se tem tabelas grandes e tem de transferir as entidades de tabela muitas vezes, recomendamos que armazene os dados em blobs de armazenamento do Azure em vez disso.

Obter um intervalo de entidades numa partição

Se não quiser consultar todas as entidades em uma partição, você pode especificar um intervalo. Combine o filtro de chave de partição com um filtro de chave de linha. O exemplo de código a seguir usa dois filtros para obter todas as entidades na partição Smith onde a chave de linha (nome) começa com uma letra anterior ao E alfabeto e, em seguida, imprime os resultados da consulta.

Nota

Estes métodos não são atualmente suportados para C++ no 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;
}  

Obter uma única entidade

Pode escrever uma consulta para obter uma entidade única e específica. O código a seguir usa table_operation::retrieve_entity para especificar o cliente Jeff Smith. Esse método retorna apenas uma entidade, em vez de uma coleção, e o valor retornado está em table_result. Especificar as chaves de partição e da fila numa consulta é a forma mais rápida de obter uma única entidade a partir do serviço Tabela.

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;

Substituir uma entidade

Para substituir uma entidade, recupere-a do serviço Tabela, modifique o objeto de entidade e, em seguida, guarde as alterações novamente no serviço Tabela. O código seguinte altera o número de telefone e o endereço de e-mail de um cliente existente. Em vez de chamar table_operation::insert_entity, este código usa table_operation::replace_entity. Essa abordagem faz com que a entidade seja totalmente substituída no servidor, a menos que a entidade no servidor tenha sido alterada desde que foi recuperada. Se tiver sido alterado, a operação falhará. Essa falha impede que seu aplicativo substitua uma alteração feita entre a recuperação e a atualização por outro componente. O tratamento adequado dessa falha é recuperar a entidade novamente, fazer suas alterações, se ainda válidas, e então fazer outra table_operation::replace_entity operação.

// 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);

Inserir ou substituir uma entidade

table_operation::replace_entity As operações falham se a entidade tiver sido alterada desde que foi recuperada do servidor. Além disso, você deve recuperar a entidade do servidor primeiro para table_operation::replace_entity ser bem-sucedido. Às vezes, você não sabe se a entidade existe no servidor. Os valores atuais armazenados nele são irrelevantes, porque sua atualização deve substituí-los todos. Para obter esse resultado, use uma table_operation::insert_or_replace_entity operação. Esta operação insere a entidade se ela não existir. A operação substitui a entidade, se ela existir. No exemplo de código a seguir, a entidade do cliente para Jeff Smith ainda é recuperada, mas é salva novamente no servidor usando table_operation::insert_or_replace_entity. Todas as atualizações efetuadas à entidade entre as operações de obtenção e atualização serão substituídas.

// 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);

Consultar um subconjunto de propriedades de entidade

Uma consulta a uma tabela pode obter apenas algumas propriedades de uma entidade. A consulta no código a seguir usa o table_query::set_select_columns método para retornar apenas os endereços de e-mail de entidades na tabela.

// 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;
}

Nota

Consultar algumas propriedades de uma entidade é uma operação mais eficiente do que obter todas as propriedades.

Eliminar conteúdo

Eliminar uma entidade

Você pode excluir uma entidade depois de recuperá-la. Depois de recuperar uma entidade, chame table_operation::delete_entity a entidade para excluir. Em seguida, chame o cloud_table.execute método. O código a seguir recupera e exclui uma entidade com uma chave de partição de Smith e uma chave de linha de 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);  

Eliminar uma tabela

Finalmente, o seguinte exemplo de código elimina uma tabela a partir de uma conta do Storage. Uma tabela que foi excluída não está disponível para ser recriada por algum tempo após a exclusão.

// 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";
}

Resolução de Problemas

Para o Visual Studio Community Edition, se seu projeto receber erros de compilação devido aos arquivos de inclusão storage_account.h e table.h, remova a opção de compilador /permissive- :

  1. No Explorador de Soluções, clique com o botão direito do rato no seu projeto e selecione Propriedades.
  2. Na caixa de diálogo Páginas de Propriedades, expanda Propriedades de Configuração, expanda C/C++e selecione Idioma.
  3. Definir Modo de conformidade para Não.

Próximos passos

O Explorador de Armazenamento do Microsoft Azure é uma aplicação autónoma e gratuita da Microsoft, que lhe permite trabalhar visualmente com dados do Armazenamento do Azure no Windows, macOS e Linux.

Siga estes links para saber mais sobre o Armazenamento do Azure e a API para Tabela no Azure Cosmos DB: