← Back to overview
November 15, 2012 · Table Storage

DictionaryTableEntity: Working with untyped entities in the Table Storage Service

About 2 weeks ago Microsoft released the new version of the Windows Azure Storage SDK, version 2.0.0.0. This version introduces a new way to work with Table Storage which is similar to the Java implementation of the SDK. Instead of working with aDataServiceContext (which comes from WCF Data Services), you'll work with operations. Here is an example of this new implementation:

  1. First we initialize the storage account, the table client and we make sure the table exists.
  2. We create a new customer which inherits from TableEntity
  3. Finally we create a TableOperation and we execute it to commit the changes.
    public class Customer : TableEntity
    {
        public string Name { get; set; }
    }

    static void CreateCustomers()
    {
        // Get the customers table.
        CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), false);
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
        CloudTable customersTable = tableClient.GetTableReference("customers");
        customersTable.CreateIfNotExists();

        // Add 2 customers.
        var customer1 = new Customer() { PartitionKey = "", RowKey = "MSFT", Name = "Microsoft" };
        customersTable.Execute(TableOperation.Insert(customer1));
        var customer2 = new Customer() { PartitionKey = "", RowKey = "GOOG", Name = "Google" };
        customersTable.Execute(TableOperation.Insert(customer2));
    }

Taking a deeper look TableEntity

You'll see a few changes compared to the oldTableServiceEntity class:

By default, these methods are implemented as follows:

As you can see, both of these methods can come in handy if you want to do something a little more advanced. Let's see how easy it is to create a new TableEntity which acts like a dictionary.

Introducing DictionaryTableEntity

The following code overrides both the ReadEntity and WriteEntity methods. When reading the entity, instead of using reflection, the list of properties is simply stored as a Dictionary in the object. When inserting or updating the entity, it will use that Dictionary and persist the values to Table Storage. This new class also implements the IDictionary interface and adds a few extra methods which make it easy to add new properties to the object.

    public class DictionaryTableEntity : TableEntity, IDictionary<string, EntityProperty>
    {
        private IDictionary<string, EntityProperty> _properties;

        public DictionaryTableEntity()
        {
            _properties = new Dictionary<string, EntityProperty>();
        }

        public override void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
        {
            this._properties = properties;
        }

        public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
        {
            return _properties;
        }

        public void Add(string key, EntityProperty value)
        {
            _properties.Add(key, value);
        }

        public void Add(string key, bool value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        public void Add(string key, byte[] value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        public void Add(string key, DateTime? value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        public void Add(string key, DateTimeOffset? value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        public void Add(string key, double value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        public void Add(string key, Guid value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        public void Add(string key, int value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        public void Add(string key, long value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        public void Add(string key, string value)
        {
            _properties.Add(key, new EntityProperty(value));
        }

        // IDirectory implementation ...
    }

Creating new entities

Ok so previously I created the Customer entity and added 2 customers. Now I want to be able to manage a bunch of information about this customer like the locations of the customer and the websites. The following implementation would even make it possible to declare the possible ‘content types' at runtime. This means you could even extend your application without having to recompile or redeploy the application.

In this code I'm doing 2 things:

The advantage here is that we can store all this information in a single partition (see how I'm using the customer's name as partition key). And as a result, we can insert or update all this information in a batch transaction.

    CloudTable customersMetadataTable = tableClient.GetTableReference("customersmetadata");
    customersMetadataTable.CreateIfNotExists();

    var msftAddress1 = new DictionaryTableEntity();
    msftAddress1.PartitionKey = "MSFT";
    msftAddress1.RowKey = "ADDRESS-" + Guid.NewGuid().ToString("N").ToUpper();
    msftAddress1.Add("city", "Seattle");
    msftAddress1.Add("street", "111 South Jackson");

    var msftWebsite1 = new DictionaryTableEntity();
    msftWebsite1.PartitionKey = "MSFT";
    msftWebsite1.RowKey = "WEBSITE-" + Guid.NewGuid().ToString("N").ToUpper();
    msftWebsite1.Add("url", "http://www.microsoft.com");

    var msftWebsite2 = new DictionaryTableEntity();
    msftWebsite2.PartitionKey = "MSFT";
    msftWebsite2.RowKey = "WEBSITE-" + Guid.NewGuid().ToString("N").ToUpper();
    msftWebsite2.Add("url", "http://www.windowsazure.com");

    var batch = new TableBatchOperation();
    batch.Add(TableOperation.Insert(msftAddress1));
    batch.Add(TableOperation.Insert(msftWebsite1));
    batch.Add(TableOperation.Insert(msftWebsite2));
    customersMetadataTable.ExecuteBatch(batch);

And with TableXplorer you can see the result:

Reading existing entities

Reading data with the DictionaryTableEntity is also very easy, you can access a specific property directly (as if the entity was a dictionary) or you could also iterate over all properties available in the current entity:

    TableQuery<DictionaryTableEntity> query =
        new TableQuery<DictionaryTableEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "MSFT"));

    var microsoftMetadata = customersMetadataTable.ExecuteQuery(query);
    foreach (var record in microsoftMetadata)
    {
        Console.WriteLine("Processing: {0}", record.RowKey);

        if (record.RowKey.StartsWith("ADDRESS"))
        {
            Console.WriteLine(" > This is an address");
            Console.WriteLine("   - Street: {0}", record["street"].StringValue);
            Console.WriteLine("   - City: {0}", record["city"].StringValue);                    
        }
        else if (record.RowKey.StartsWith("WEBSITE"))
        {
            Console.WriteLine(" > This is an website");
            Console.WriteLine("   - Url: {0}", record["url"].StringValue);
        }

        Console.WriteLine(" > All properties");
        foreach (var property in record)
            Console.WriteLine("   - {0}: {1}", property.Key, property.Value.StringValue);
    }

To get started simply grab DictionaryTableEntity.cs from GitHub and you're good to go.

Enjoy!

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket
Comments powered by Disqus