Приступая к работе с хранилищем таблиц Azure с помощью .NET

Совет

См. примеры кода в репозитории службы хранилища Azure

Полные и простые в применении примеры кода для службы хранилища Azure можно скачать и запустить отсюда.

Обзор

Хранилище таблиц Azure — это служба в облаке, в которой хранятся структурированные данные NoSQL. Хранилище таблиц — это хранилище ключей и атрибутов, реализованное в виде бессхемной конструкции. Такая конструкция хранилища таблиц позволяет легко адаптировать данные по мере расширения приложения. Быстрый и экономичный доступ к данным предоставляется приложениям всех видов. Табличное хранилище обычно значительно дешевле, чем традиционная база данных SQL для тех же объемов данных.

Табличное хранилище можно использовать для хранения гибких наборов данных, например пользовательских данных для веб-приложений, адресных книг, сведений об устройстве, а также метаданных любого другого типа, которые требуются вашей службе. В таблице можно хранить любое количество сущностей, а учетная запись хранения может содержать любое количество таблиц в пределах емкости учетной записи.

О данном учебнике

В этом руководстве показано, как написать код .NET для некоторых распространенных сценариев использования хранилища таблиц Azure, включая создание и удаление таблиц, а также вставку, обновление, удаление и создание запросов к данным таблиц.

Предварительные требования:

Примечание

Мы советуем использовать последнюю версию клиентской библиотеки службы хранилища Azure для .NET для работы с этим учебником. Последняя версия библиотеки — 7.x. Ее можно загрузить на веб-сайте Nuget. Источник клиентской библиотеки можно найти на сайте GitHub.

Если вы используете эмулятор хранения, обратите внимание, что версия 7.x клиентской библиотеки работает с эмулятором хранения не ниже версии 4.3.

Другие примеры

Дополнительные примеры использования хранилища таблиц см. в статье Getting Started with Azure Table Storage in .NET (Приступая к работе с хранилищем таблиц Azure в .NET). Вы можете скачать пример приложения и запустить его или просмотреть код на GitHub.

Что такое служба таблиц

В службе хранилища таблиц Azure хранятся большие объемы структурированных данных. Эта служба — хранилище данных NoSQL, которое принимает вызовы внутри и снаружи облака Azure с проверкой подлинности. Таблицы Azure идеально подходят для хранения нереляционных структурированных данных. Наиболее частые способы использования службы таблицы включают следующие.

  • Хранение терабайтов структурированных данных с возможностью обслуживания приложений с веб-масштабированием.
  • Хранение наборов данных, которые не требуют сложных соединений, внешних ключей или хранимых процедур и могут быть денормализованы для обеспечения быстрого доступа.
  • Быстрый запрос данных с помощью кластерного индекса.
  • Доступ к данным с помощью протокола OData и запросов LINQ с библиотеками .NET службы данных WCF.

Службу таблиц можно использовать для хранения и запросов огромных наборов структурированных нереляционных данных, и таблица будет масштабироваться при запросе на увеличение.

Основные понятия службы таблиц

Служба таблиц содержит следующие компоненты:

Table1

  • Формат URL-адреса. Код обращается к таблицам в учетной записи, используя следующий формат адреса:
    http://<storage account>.table.core.windows.net/<table>

    К таблицам Azure можно обратиться напрямую, используя этот адрес с протоколом OData. Дополнительные сведения см. на сайте OData.org.

  • Учетная запись хранения. Весь доступ к хранилищу Azure осуществляется с помощью учетной записи хранения. Сведения об емкости учетной записи хранения см. в статье Целевые показатели масштабируемости и производительности службы хранилища Azure.
  • Таблица. Таблица — это коллекция сущностей. Таблицы не налагают схему на сущности. Это означает, что одна таблица может содержать сущности, которые имеют различные наборы свойств. Количество таблиц, которые может содержать учетная запись хранения, ограничены только емкостью учетной записи хранения.
  • Сущность.Сущность — это набор свойств подобно строке базы данных. Сущность может быть размером до 1 МБ.
  • Свойства.Свойство представляет собой пару "имя-значение". Каждая сущность может содержать до 252 свойств для хранения данных. Каждая сущность имеет также 3 системных свойства, которые определяют ключ раздела, ключ строки и отметку времени. Сущности с тем же ключом раздела можно запросить быстрее, и они добавляются или обновляются с помощью атомарных операций. Ключ строки сущности — это ее уникальный код внутри раздела.

Дополнительные сведения об именовании таблиц и ее свойствах см. в обзорной статье о модели данных службы таблиц.

Создание учетной записи хранения Azure

Самый простой способ создать первую учетную запись хранения Azure — воспользоваться порталом Azure. Дополнительную информацию см. в статье Об учетных записях хранения Azure.

Кроме того, создать учетную запись хранения Azure можно с помощью Azure PowerShell, Azure CLI или клиентской библиотеки поставщика ресурсов хранилища для .NET.

Если вы не хотите сейчас создавать учетную запись хранения, код можно протестировать в локальной среде с помощью эмулятора хранения Azure. Дополнительные сведения см. в статье Использование эмулятора хранения Azure для разработки и тестирования.

Настройка среды разработки

Теперь настройте среду разработки в Visual Studio, чтобы вы могли работать с примером кода из этого руководства.

Создание нового проекта консольного приложения Windows

В Visual Studio создайте новое консольное приложение Windows:

Создание консольного приложения Windows

Все примеры кода из этого руководства можно добавить в метод Main() в консольном приложении program.cs.

Обратите внимание, что вы можете использовать клиентскую библиотеку службы хранилища Azure из любого приложения .NET, в том числе из облачной службы Azure, веб-приложения Azure, классического приложения или мобильного приложения. Для упрощения в этом руководстве мы будем использовать консольное приложение.

Установка необходимых пакетов с помощью NuGet

Для работы с этим руководством вам нужно установить в проект два пакета.

Вы можете использовать NuGet для установки обоих пакетов. Выполните следующие действия.

  1. Щелкните правой кнопкой мыши проект в обозревателе решений и выберите Управление пакетами NuGet.
  2. Выполните в Интернете поиск по запросу "WindowsAzure.Storage" и нажмите кнопку Установить , чтобы установить клиентскую библиотеку службы хранилища и зависимые компоненты.
  3. Выполните поиск в Интернете по запросу "ConfigurationManager" и нажмите кнопку Установить , чтобы установить Azure Configuration Manager.
Примечание

Клиентская библиотека службы хранилища также доступна в пакете Azure SDK для .NET. Но мы рекомендуем также установить клиентскую библиотеку службы хранилища из NuGet, чтобы всегда иметь ее последнюю версию.

Зависимости ODataLib в клиентской библиотеке хранилища для .NET разрешаются через пакеты ODataLib (версии 5.0.2 и выше), доступные через NuGet, а не через службы данных WCF. Библиотеки ODataLib можно загрузить напрямую или указать на них ссылку в проекте через NuGet. К специальным пакетам ODataLib, используемым клиентскими библиотеками хранения, относятся OData, Edm и Spatial. Хотя эти библиотеки используются классами хранилища таблиц Azure, они являются обязательными зависимостями для программирования с использованием клиентской библиотеки хранения.

Определение целевой среды

Примеры из этого руководства можно выполнять в двух средах.

  • Вы можете выполнить код в учетной записи хранения Azure в облаке.
  • Вы можете выполнить код в эмуляторе хранения Azure. Эмулятор хранения — это локальная среда, эмулирующая учетную запись хранения Azure в облаке. Эмулятор можно использовать как бесплатный вариант для тестирования и отладки кода, пока приложение находится на стадии разработки. Эмулятор использует известную учетную запись и ключ. Дополнительные сведения см. в статье Использование эмулятора хранения Azure для разработки и тестирования.

Выбрав учетную запись хранения в облаке, скопируйте первичный ключ доступа к этой учетной записи хранения с портала Azure. Дополнительные сведения см. в разделе Просмотр и копирование ключей доступа к хранилищу.

Примечание

Вы можете указать эмулятор хранения, чтобы избежать затрат, связанных с хранилищем Azure. Однако если вы выберете учетную запись хранения Azure в облаке, затраты на выполнение заданий в учебнике будут незначительны.

Настройка строки подключения хранилища

Библиотека клиента хранилища Azure для .NET поддерживает использование строки подключения для настройки конечных точек и учетных данных для доступа к службам хранилища. Строку подключения хранилища рекомендуется хранить в файле конфигурации.

Дополнительные сведения о строках подключения см. в статье Настройка строк подключения службы хранилища Azure.

Примечание

Ключ учетной записи хранения похож на корневой пароль для вашей учетной записи хранения. Не забудьте защитить ключ учетной записи хранения. Не сообщайте его другим пользователям, не определяйте его в коде и не храните его в текстовом файле, доступном другим пользователям. Повторно создайте ключ с помощью портала Azure, если вы считаете, что он мог быть взломан.

Чтобы настроить строку подключения, откройте файл app.config в обозревателе решений Visual Studio. Добавьте содержимое элемента <appSettings> , показанное ниже. Замените account-name именем своей учетной записи хранения, а account-key — ключом доступа своей учетной записи:

<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
      <appSettings>
        <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key" />
      </appSettings>
</configuration>

Например, параметр конфигурации будет приблизительно таким:

<add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=storagesample;AccountKey=nYV0gln6fT7mvY+rxu2iWAEyzPKITGkhM88J8HUoyofvK7C6fHcZc2kRZp6cKgYRUM74lHI84L50Iau1+9hPjB==" />

Чтобы указать эмулятор хранения, можно использовать ярлык, который сопоставляется с хорошо известным именем и ключом. В этом случае параметр строки подключения будет таким:

<add key="StorageConnectionString" value="UseDevelopmentStorage=true;" />

Добавление объявлений пространств имен

Добавьте в начало файла program.cs следующие инструкции using.

using Microsoft.Azure; // Namespace for CloudConfigurationManager
using Microsoft.WindowsAzure.Storage; // Namespace for CloudStorageAccount
using Microsoft.WindowsAzure.Storage.Table; // Namespace for Table storage types

Анализ строки подключения

Библиотека Microsoft Azure Configuration Manager для .NET содержит класс для анализа строки подключения из файла конфигурации. Класс CloudConfigurationManager анализирует параметры конфигурации независимо от того, где работает клиентское приложение — на настольном компьютере, мобильном устройстве, виртуальной машине Azure или в облачной службе Azure.

Для ссылки на пакет CloudConfigurationManager добавьте следующую директиву using:

using Microsoft.Azure;    //Namespace for CloudConfigurationManager

Ниже приведен пример, в котором показано получение строки подключения из файла конфигурации.

// Parse the connection string and return a reference to the storage account.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

Использование диспетчера конфигураций Azure не является обязательным. Вы также можете использовать API, например класс ConfigurationManager для .NET Framework.

Создание клиента службы таблиц

Класс CloudTableClient позволяет получать таблицы и сущности, хранящиеся в хранилище таблиц. Вот один из способов создать клиента службы.

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

Теперь вы можете написать код, который считывает и записывает данные в хранилище таблиц.

Создание таблицы

В этом примере показано, как создать таблицу, если она не существует:

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Retrieve a reference to the table.
CloudTable table = tableClient.GetTableReference("people");

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

Добавление сущности в таблицу

Сущности сопоставляются с объектами C# с помощью настраиваемого класса, производного от TableEntity. Чтобы добавить сущность в таблицу, создайте класс, который определяет свойства сущности. Следующий код определяет класс сущностей, который использует имя клиента как ключ строки, а фамилию клиента — как ключ раздела. Вместе ключ раздела и ключ строки сущности уникальным образом идентифицируют сущность в таблице. Сущности с одинаковым ключом раздела можно запрашивать быстрее, чем с разными ключами раздела, но использование различных ключей разделов обеспечивает более высокую масштабируемость параллельных операций. Любое свойство, которое будет храниться в службе таблиц, должно быть открытым свойством поддерживаемого типа, предоставляющим возможности задания и получения значений. Кроме того, тип сущности должен предоставлять конструктор без параметров.

public class CustomerEntity : TableEntity
{
    public CustomerEntity(string lastName, string firstName)
    {
        this.PartitionKey = lastName;
        this.RowKey = firstName;
    }

    public CustomerEntity() { }

    public string Email { get; set; }

    public string PhoneNumber { get; set; }
}

Табличные операции, включающие сущности, выполняются с использованием объекта CloudTable , созданного ранее в разделе "Создание таблицы". Выполняемая операция представляется объектом TableOperation . В следующем примере кода показано создание объекта CloudTable и объекта CustomerEntity. Чтобы подготовить операцию, создается объект TableOperation для вставки сущности customer в таблицу. Наконец, операция выполняется путем вызова CloudTable.Execute.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable object that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Create a new customer entity.
CustomerEntity customer1 = new CustomerEntity("Harp", "Walter");
customer1.Email = "Walter@contoso.com";
customer1.PhoneNumber = "425-555-0101";

// Create the TableOperation object that inserts the customer entity.
TableOperation insertOperation = TableOperation.Insert(customer1);

// Execute the insert operation.
table.Execute(insertOperation);

Вставка пакета сущностей

Вы можете вставить пакет сущностей в таблицу в одной операции записи. Некоторые другие примечания к пакетным операциям:

  • Можно выполнять операции обновления, удаления и вставки в одной операции пакета.
  • Одна пакетная операция может включать до 100 сущностей.
  • У всех сущностей в одной пакетной операции должен быть одинаковый ключ раздела.
  • Хотя запрос можно выполнить как пакетную операцию, он должен быть единственной операцией в пакете.

В следующем примере кода создается два объекта сущности, которые добавляются в TableBatchOperation с помощью метода Insert. Затем вызывается метод CloudTable.Execute для выполнения операции.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable object that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Create the batch operation.
TableBatchOperation batchOperation = new TableBatchOperation();

// Create a customer entity and add it to the table.
CustomerEntity customer1 = new CustomerEntity("Smith", "Jeff");
customer1.Email = "Jeff@contoso.com";
customer1.PhoneNumber = "425-555-0104";

// Create another customer entity and add it to the table.
CustomerEntity customer2 = new CustomerEntity("Smith", "Ben");
customer2.Email = "Ben@contoso.com";
customer2.PhoneNumber = "425-555-0102";

// Add both customer entities to the batch insert operation.
batchOperation.Insert(customer1);
batchOperation.Insert(customer2);

// Execute the batch operation.
table.ExecuteBatch(batchOperation);

Получение всех сущностей в разделе

Чтобы запросить таблицу для всех сущностей в разделе, используйте объект TableQuery . Следующий пример кода задает фильтр для сущностей с ключом раздела Smith. Этот пример выводит на консоль поля каждой сущности в результатах запроса.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable object that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Construct the query operation for all customer entities where PartitionKey="Smith".
TableQuery<CustomerEntity> query = new TableQuery<CustomerEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Smith"));

// Print the fields for each customer.
foreach (CustomerEntity entity in table.ExecuteQuery(query))
{
    Console.WriteLine("{0}, {1}\t{2}\t{3}", entity.PartitionKey, entity.RowKey,
        entity.Email, entity.PhoneNumber);
}

Получение диапазона сущностей в разделе

Если вы не хотите запрашивать все сущности в разделе, можно указать диапазон, объединив фильтр ключа раздела с фильтром ключа строк. В следующем примере кода используются два фильтра для получения всех сущностей в разделе Smith, где ключ строки (имя) начинается с первой буквы алфавита до буквы E, после чего результаты запроса выводятся в консоль.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable object that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Create the table query.
TableQuery<CustomerEntity> rangeQuery = new TableQuery<CustomerEntity>().Where(
    TableQuery.CombineFilters(
        TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Smith"),
        TableOperators.And,
        TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, "E")));

// Loop through the results, displaying information about the entity.
foreach (CustomerEntity entity in table.ExecuteQuery(rangeQuery))
{
    Console.WriteLine("{0}, {1}\t{2}\t{3}", entity.PartitionKey, entity.RowKey,
        entity.Email, entity.PhoneNumber);
}

Извлечение одной сущности

Можно написать запрос для получения отдельной сущности. В следующем примере кода с помощью объекта TableOperation задается клиент Ben Smith. Этот метод возвращает только одну сущность, а не коллекцию, а возвращаемое значение в TableResult.Result является объектом CustomerEntity. Указание ключа раздела и ключа строки в запросе — самый быстрый способ извлечь одну сущность из службы таблиц.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable object that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Create a retrieve operation that takes a customer entity.
TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

// Execute the retrieve operation.
TableResult retrievedResult = table.Execute(retrieveOperation);

// Print the phone number of the result.
if (retrievedResult.Result != null)
{
    Console.WriteLine(((CustomerEntity)retrievedResult.Result).PhoneNumber);
}
else
{
    Console.WriteLine("The phone number could not be retrieved.");
}

Замена сущности

Чтобы обновить сущность, извлеките ее из службы таблиц, измените объект сущности и сохраните изменения в службе таблиц. Следующий код изменяет существующий номер телефона клиента. Вместо вызова метода Insert этот код использует Replace. Из-за этого сущность будет полностью заменена на сервере, если только сущность на сервере не была изменена с момента извлечения. В подобном случае операция не будет выполнена. Это необходимо, чтобы приложение случайно не перезаписало изменения, внесенные с момента извлечения до обновления другим компонентом приложения. Правильный алгоритм обработки этой ошибки заключается в том, чтобы снова получить сущность, внести необходимые изменения (если это еще возможно), а затем выполнить еще одну операцию Replace. Ниже показано, как изменить это поведение.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable object that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Create a retrieve operation that takes a customer entity.
TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

// Execute the operation.
TableResult retrievedResult = table.Execute(retrieveOperation);

// Assign the result to a CustomerEntity object.
CustomerEntity updateEntity = (CustomerEntity)retrievedResult.Result;

if (updateEntity != null)
{
    // Change the phone number.
    updateEntity.PhoneNumber = "425-555-0105";

    // Create the Replace TableOperation.
    TableOperation updateOperation = TableOperation.Replace(updateEntity);

    // Execute the operation.
    table.Execute(updateOperation);

    Console.WriteLine("Entity updated.");
}
else
{
    Console.WriteLine("Entity could not be retrieved.");
}

Вставка или замена сущности

Replace завершаются ошибкой, если сущность была изменена с момента получения с сервера. Более того, для успешного выполнения операции Replace сначала нужно получить сущность с сервера. Тем не менее иногда вы не знаете, существует ли сущность на сервере и являются ли текущие значения, хранящиеся на нем, актуальными. Обновление должно заменить их все. Для выполнения этой задачи необходимо использовать операцию InsertOrReplace . Эта операция вставляет сущность, если она не существует, или заменяет ее, если она существует, независимо от того, когда было выполнено последнее обновление. В следующем примере кода сущность клиента для Ben Smith все равно извлекается, но затем она сохраняется на сервере с помощью InsertOrReplace. Любые обновления сущности, внесенные между операциями извлечения и обновления, будут перезаписаны.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable object that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Create a retrieve operation that takes a customer entity.
TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

// Execute the operation.
TableResult retrievedResult = table.Execute(retrieveOperation);

// Assign the result to a CustomerEntity object.
CustomerEntity updateEntity = (CustomerEntity)retrievedResult.Result;

if (updateEntity != null)
{
    // Change the phone number.
    updateEntity.PhoneNumber = "425-555-1234";

    // Create the InsertOrReplace TableOperation.
    TableOperation insertOrReplaceOperation = TableOperation.InsertOrReplace(updateEntity);

    // Execute the operation.
    table.Execute(insertOrReplaceOperation);

    Console.WriteLine("Entity was updated.");
}
else
{
    Console.WriteLine("Entity could not be retrieved.");
}

Запрос подмножества свойств сущности

Запрос к таблице может получить лишь несколько свойств сущности, а не все свойства. Этот метод, который называется "проекцией", снижает потребление пропускной способности и может повысить производительность запросов, особенно для крупных сущностей. Запрос в следующем коде возвращает только электронные адреса сущностей в таблице. Это делается с помощью запроса DynamicTableEntity, а также EntityResolver. Дополнительные сведения о проекции см. в записи блога Windows Azure Tables: Introducing Upsert and Query Projection (Таблицы Microsoft Azure: введение в Upsert и проекции в запросах). Обратите внимание, что проекция не поддерживается в локальном эмуляторе хранения, поэтому этот код выполняется только при использовании учетной записи хранения в службе таблиц.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Define the query, and select only the Email property.
TableQuery<DynamicTableEntity> projectionQuery = new TableQuery<DynamicTableEntity>().Select(new string[] { "Email" });

// Define an entity resolver to work with the entity after retrieval.
EntityResolver<string> resolver = (pk, rk, ts, props, etag) => props.ContainsKey("Email") ? props["Email"].StringValue : null;

foreach (string projectedEmail in table.ExecuteQuery(projectionQuery, resolver, null, null))
{
    Console.WriteLine(projectedEmail);
}

Удаление сущности

Сущность можно легко удалить после ее получения с использованием того же шаблона, что и для обновления сущностей. Следующий код извлекает и удаляет сущность клиента.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Create a retrieve operation that expects a customer entity.
TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>("Smith", "Ben");

// Execute the operation.
TableResult retrievedResult = table.Execute(retrieveOperation);

// Assign the result to a CustomerEntity.
CustomerEntity deleteEntity = (CustomerEntity)retrievedResult.Result;

// Create the Delete TableOperation.
if (deleteEntity != null)
{
    TableOperation deleteOperation = TableOperation.Delete(deleteEntity);

    // Execute the operation.
    table.Execute(deleteOperation);

    Console.WriteLine("Entity deleted.");
}
else
{
    Console.WriteLine("Could not retrieve the entity.");
}

Удаление таблицы

Наконец, следующий пример кода удаляет таблицу из учетной записи хранения. Удаленную таблицу нельзя воссоздать в течение определенного времени после удаления.

// Retrieve the storage account from the connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

// Create the CloudTable that represents the "people" table.
CloudTable table = tableClient.GetTableReference("people");

// Delete the table it if exists.
table.DeleteIfExists();

Асинхронное получение объектов со страниц

Если необходимо считать большое количество объектов, обрабатывая или отображая их по мере получения (до завершения всей операции), для их получения можно использовать сегментированный запрос. В этом примере объясняется, как расположить запрошенные результаты на странице с помощью алгоритма Async-Await для того, чтобы не блокировать выполнение задачи ожиданием большого объема возвращаемых данных. Дополнительные сведения об использовании алгоритма Async-Await в .NET см. в статье Асинхронное программирование с использованием ключевых слов Async и Await (C# и Visual Basic).

// Initialize a default TableQuery to retrieve all the entities in the table.
TableQuery<CustomerEntity> tableQuery = new TableQuery<CustomerEntity>();

// Initialize the continuation token to null to start from the beginning of the table.
TableContinuationToken continuationToken = null;

do
{
    // Retrieve a segment (up to 1,000 entities).
    TableQuerySegment<CustomerEntity> tableQueryResult =
        await table.ExecuteQuerySegmentedAsync(tableQuery, continuationToken);

    // Assign the new continuation token to tell the service where to
    // continue on the next iteration (or null if it has reached the end).
    continuationToken = tableQueryResult.ContinuationToken;

    // Print the number of rows retrieved.
    Console.WriteLine("Rows retrieved {0}", tableQueryResult.Results.Count);

// Loop until a null continuation token is received, indicating the end of the table.
} while(continuationToken != null);

Дальнейшие действия

Вы изучили основные сведения о табличном хранилище. Дополнительные сведения о более сложных задачах по использованию хранилища можно найти по следующим ссылкам.