Skip to content
March 12, 2012 / ahriman hpc mode

Основы хранилища Windows Azure. Таблицы.

Таблицы

clip_image001

Сервис таблиц в Windows Azure не является реляционным.

Нельзя-

1) Создавать внешние ключи между таблицами.

2) Выполнять операцию объединения на стороне сервера

3) Создавать произвольные индексы

4) Выполнять такие функции, как, например, Count(), на стороне сервера

Применение сервиса таблиц актуально, если вам не требуется реляционное хранилище или если вам не нужны операции объединения (joins) на стороне сервера, а также в тех случаях, когда набор данных не очень велик и операции объединения можно обрабатывать на стороне клиента с помощью LINQ. Кроме этого, стоит оценить выгоды использования сервиса таблиц хранилища Windows Azure в том случае, если данных у вас больше, чем максимальный объем, поддерживаемый SQL Azure (который в настоящее время составляет 150 Гб). Заметьте

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

Для доступа к сервису таблиц вы можете использовать REST API, совместимый с WCF Data Services (ранее ADO.NET Data Services Framework). Для чтения и записи данных в сервис таблиц в упражнении используется WCF Data Services Client Library (ранее .NET Client Library).

Запись в таблицах состоит из следующих компонентов и концепций:

  • Свойство (столбец) – значение сущности. Имена свойств регистрочувствительны.
  • PartitionKey – первое обязательное свойство каждой таблицы, используемое системой для автоматической балансировки нагрузки и распределения сущностей таблицы между серверами.
  • RowKey – второе обязательно свойство для акждой таблицы, являющееся уникальным ID сущности внутри партиции, в которой оно расположено, и являющееся вторым компонентом в комбинации с RowKey, уникально идентифицирующей сущность в таблице.
  • Timestamp – каждая сущность имеет версию, управляемую системой, необходимую для оптимистического параллелизма.

Пример: POCO, наследуемый от TableServiceEntity

public class MyClass : TableServiceEntity
        {

            public MyClass()
            {

                base.PartitionKey = "Clients";

                base.RowKey = Guid.NewGuid().ToString();

            }

            public MyClass(string PartitionKey, string RowKey)
            {

                base.PartitionKey = PartitionKey;

                base.RowKey = RowKey;

            }

            public string FName { get; set; }

            public string LName { get; set; }

        }

Пример: сокращенная запись

public MyClass():base("Clients", Guid.NewGuid().ToString())
{
}

public MyClass(string PartitionKey, string RowKey):base(PartitionKey,RowKey)
{
}

Класс TableServiceEntity является частью библиотеки Microsoft.WindowsAzure.StorageClient. Он определяет системные свойства PartititionKey, RowKey и TimeStamp, необходимые для каждой сущности в таблице Windows Azure. данном случае мы определяем для свойства PartitionKey фиксированное значение. В реальной ситуации лучше выбирать значение, обеспечивающее балансировку нагрузки между узлами хранилища, динамическое вычисляемое значение, например, день добавления сущности и так далее.

  • Порядок сортировки – есть единственный индекс в таблицах, когда таблицы сортируются по сначала PartitionKey, после чего по RowKey, что означает, что записи, указывающие эти ключи, будут более эффективны, и результаты будут сортироваться сначала по PartitionKey и потом по RowKey.
  • Типы – PartitionKey и RowKey должны быть типа string, остальные свойства: Binary, Bool, DateTime, Double, GUID, Int, Int64, String.
  • Нет фиксированной схемы – в таблицах Windows Azure нет схем, поэтому все свойства хранятся в парах ключ-типизированное значение, что означает, что две сущности в одной таблице могут иметь разные свойства. В таблице может быть даже два свойства с одинаковым имене, но разными типами для значения свойства. В пределах одной сущности имена свойств должны быть уникальными.

Ссылка на таблицу выглядит стандартно для именования сущностей в сервисах хранилища Windows Azure:

http://<account&gt;.table.core.windows.net/<TableName>

Рекомендация: таблицы данных должны создаваться только один раз. Обычно этот процесс выполняется на стадии подготовки и редко – в коде приложения. Application_Start в классе Global является рекомендуемым местом для помещения логики инициализации.

void Application_Start(object sender, EventArgs e) { CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) => { var connectionString = RoleEnvironment. GetConfigurationSettingValue(configName); configSettingPublisher(connectionString); }); //получение данных из настроек аккаунта хранилища, в данном случае это строка подключения DataStorage

var account = CloudStorageAccount.FromConfigurationSetting("DataStorage");

//создание таблиц согласно контексту данных CloudTableClient.CreateTablesFromModel(typeof(MyClassDataContext), account.TableEndpoint.AbsoluteUri, account.Credentials); }

Для удобства и аккуратности программирования необходимо выполнять все операции над определенными таблицами из соответствующих классов контекстов, которые наследуются от класса DataServiceContext.

using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace WebRole
{
    public class MyClassDataContext : TableServiceContext
    {
        public MyClassDataContext(string baseAddress, StorageCredentials credentials)
            : base(baseAddress, credentials)
        {
        }

        public IQueryable<MyClass> units
        {
            get
            {
                return this.CreateQuery<MyClass>("units");
            }
        }
    }

}

Для использования и манипуляций над содержимым таблицы необходимо создать объект типа CloudTableClient, предоставляющий следующую функциональность:

CreateTable – создание таблицы с определенным именем. В случае наличия таблицы с таким именем будет выброшено исключение StorageClientException. Наиболее предпочитаемым способом создания таблиц является их создание с помощью класса контекста.

CloudTableClient.CreateTablesFromModel(typeof(MyClassDataContext),
                                    account.TableEndpoint.AbsoluteUri, account.Credentials);
        }

CreateTableIfNotExist – создание таблицы с определенным именем только в том случае если ее не существует.

DoesTableExist – проверка на существование таблицы с определенным именем.

DeleteTable – удаление таблицы и ее содержимого из хранилища. если этой таблицы не существует, будет выброшено исключение StorageClientException.

DeleteTableIfExist – удаление таблицы и содержимого из хранилища только в том случае если она существует.

        public static void DeleteTable()
        {

            var account = CloudStorageAccount.FromConfigurationSetting("DataStorage");
            account.CreateCloudTableClient().DeleteTableIfExist("units");

        }

ListTables – получение списка всех таблиц. Возможно указание префикса для фильтрации имен таблиц.

        public static void GetListTables()
        {
            var account = CloudStorageAccount.FromConfigurationSetting("DataStorage");
            IEnumerable<string> tables = account.CreateCloudTableClient().ListTables("mytableprefix");
            foreach (var table in tables)
            {
                System.Diagnostics.Trace.WriteLine(table);
            }
            
        }

AddObject – добавление сущности в таблицу.

public static void AddEntityToTable(){

 

var account = CloudStorageAccount.FromConfigurationSetting("DataStorage"); var tableClient = account.CreateCloudTableClient(); TableServiceContext ctx = tableClient.GetDataServiceContext(); MyClass unit = new MyClass("Alex", "Belotserkovskiy"); unit.FName = “FName”;

unit.LName = “LName”;

ctx.AddObject("mytable", customer1); serviceContext.SaveChangesWithRetries();

}

В том случае, если у вас происходит создание множества сущностей, дешевле (с позиции количества транзакций) и быстрее будет выполнить пакет запросов. Для этого всего лишь надо передать в SaveChangesWithRetries аргумент. Пакеты запросов характеризуются:

  1. В пакете можно совершать запросы update, delete и insert.
  2. Один пакет может содержать до 100 сущностей.
  3. Все сущности в одном пакете должны иметь один partition key.
ctx.SaveChangesWithRetries(SaveChangesOptions.Batch);

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

CloudTableQuery<MyClass> qry =
    (from e in ctx.CreateQuery<MyClass>("mytable")
     where e.PartitionKey == "Belotserkovskiy" && e.FName == “Alex”
     select e).AsTableServiceQuery<MyClass>();

foreach (MyClass unit in qry)
{
    Console.WriteLine("{0}, {1}",  unit.PartitionKey, unit.FName);
}

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

MyClass unit = (from e in ctx.CreateQuery<MyClass>("mytable") where e.PartitionKey == "Belotserkovskiy" && e.FName == “Alex” select e).AsTableServiceQuery<MyClass>().FirstOrDefault();

unit.FName= "Mike"; ctx.UpdateObject(unit); ctx.SaveChangesWithRetries();

 

ctx.DeleteObject(unit);

ctx.SaveChangesWithRetries();

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: