Gaurav Mantri's Personal Blog.

Storage Client Library 2.0 – Migrating Table Storage Code

Recently with the release of SDK 1.8 for Windows Azure, the Windows Azure Storage Team announced the availability of the next version of storage client library (version 2.0). The new library is significantly different than the previous version and from what I know, it has been written from ground up to achieve better performance and is more user friendly. Because it is significantly different, upgrading from previous version (1.7) to this version is not trivial.

In this blog post, I will attempt to provide some code sample through which I will try and demonstrate how you can do some common tasks when working with Azure Table Storage. What I did is wrote two simple console applications: one which uses storage client library version 1.7 and the other which uses version 2.0 and in those two applications I demonstrated some simple functionality.

Read These First

Since version 2.0 library is significantly different than the previous ones, before you decide to upgrade your code to make use of this version I strongly urge you to read up the following blog posts by the storage team as there’re many breaking changes.

Introducing Windows Azure Storage Client Library 2.0 for .NET and Windows Runtime

http://blogs.msdn.com/b/windowsazurestorage/archive/2012/10/29/introducing-windows-azure-storage-client-library-2-0-for-net-and-windows-runtime.aspx

Windows Azure Storage Client Library 2.0 Breaking Changes & Migration Guide

http://blogs.msdn.com/b/windowsazurestorage/archive/2012/10/29/windows-azure-storage-client-library-2-0-breaking-changes-amp-migration-guide.aspx

Windows Azure Storage Client Library 2.0 Tables Deep Dive

http://blogs.msdn.com/b/windowsazurestorage/archive/2012/11/06/windows-azure-storage-client-library-2-0-tables-deep-dive.aspx

Getting Started

Before jumping into the code, there’re a few things I would like to mention:

Storage Client Libraries

To get the reference for storage client library 1.7, you can browse your local computer and navigate to the Azure SDK installation directory (C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\2012-10\ref – assuming you have SDK 1.8 installed) and select Microsoft.WindowsAzure.StorageClient.dll from there. For SDK 1.7 project, you would also need to add reference to System.Data.Services.Client.dll as well.

To get the reference for storage client library 2.0 (or the latest version for that matter), I would actually recommend getting this using Nuget. That way you’ll always get the latest version. You can simply get it by executing the following command in Nuget Package Manager console: Install-Package WindowsAzure.Storage. While it’s an easy way to get the latest version upgrades, one must not upgrade it before ensuring the new version won’t break anything in the existing code.

Sample Entity

For the purpose of demonstration, I created a simple entity called “CustomerEntity”. With version 1.7, it derives from TableServiceEntity class and with version 2.0, it derives from TableEntity class. Please note that with version 2.0, storage team has also made available a DynamicTableEntity class which comes in handy to fully exploit the No-SQL schema-less support in Azure Table Storage. While TableEntity and other mechanisms also fully exploits the N0-SQL schema-less support in Azure Table Storage, DynamicTableEntity comes in real handy when you don’t know about the object model before hand. In this blog post, we will focus on TableEntity though. Also for the sake of simplicity, I have kept the PartitionKey as “Customer” and assigned a GUID for RowKey.

For version 1.7, the customer entity looks something like this:

 
    public class CustomerEntity : TableServiceEntity
    {
        public CustomerEntity()
        {
            PartitionKey = "Customer";
            RowKey = Guid.NewGuid().ToString();
        }

        public string FirstName
        {
            get;
            set;
        }

        public string LastName
        {
            get;
            set;
        }

        public DateTime? LastOrderDate
        {
            get;
            set;
        }
    }

For version 2.0, the customer entity looks something like this:

 

    public class CustomerEntity : TableEntity
    {
        public CustomerEntity()
        {
            PartitionKey = "Customer";
            RowKey = Guid.NewGuid().ToString();
        }

        public string FirstName
        {
            get;
            set;
        }

        public string LastName
        {
            get;
            set;
        }

        public DateTime? LastOrderDate
        {
            get;
            set;
        }
    }

Operations

Now let’s see how you can perform some operations. What I’ve done is first showed how you did an operation with version 1.7 and then how would you do the same operation with version 2.0.

Create Table

If you’re using the following code with version 1.7 to create a table:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            cloudTableClient.CreateTableIfNotExist(tableName);

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            table.CreateIfNotExists();

Delete Table

If you’re using the following code with version 1.7 to delete a table:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            cloudTableClient.DeleteTableIfExist(tableName);

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            table.DeleteIfExists();

Insert Entity

If you’re using the following code with version 1.7 to insert an entity:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-10)
            };

            var serviceContext = cloudTableClient.GetDataServiceContext();
            serviceContext.AddObject(tableName, customer);
            serviceContext.SaveChangesWithRetries();

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-10)
            };

            CloudTable table = cloudTableClient.GetTableReference(tableName);
            TableOperation insertOperation = TableOperation.Insert(customer);
            table.Execute(insertOperation);

Delete Entity

If you’re using the following code with version 1.7 to delete an entity:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CustomerEntity customer = GetCustomerEntityFromSomePlace();

            var serviceContext = cloudTableClient.GetDataServiceContext();
            serviceContext.AttachTo(tableName, customer, "*");
            serviceContext.DeleteObject(customer);
            serviceContext.SaveChangesWithRetries();

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CustomerEntity customer = GetCustomerEntityFromSomePlace();

            CloudTable table = cloudTableClient.GetTableReference(tableName);
            TableOperation deleteOperation = TableOperation.Delete(customer);
            table.Execute(deleteOperation);

Replace Entity

If you’re using the following code with version 1.7 to replace an entity:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CustomerEntity customer = GetCustomerEntityFromSomePlace();
            customer.LastOrderDate = null;
            var serviceContext = cloudTableClient.GetDataServiceContext();
            serviceContext.AttachTo(tableName, customer, "*");
            serviceContext.UpdateObject(customer);
            serviceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CustomerEntity customer = GetCustomerEntityFromSomePlace();
            customer.LastOrderDate = null;
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            TableOperation replaceOperation = TableOperation.Replace(customer);
            table.Execute(replaceOperation);

Merge Entity

If you’re using the following code with version 1.7 to merge an entity:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CustomerEntity customer = GetCustomerEntityFromSomePlace();
            customer.LastOrderDate = DateTime.UtcNow;
            var serviceContext = cloudTableClient.GetDataServiceContext();
            serviceContext.AttachTo(tableName, customer, "*");
            serviceContext.UpdateObject(customer);
            serviceContext.SaveChangesWithRetries();

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CustomerEntity customer = GetCustomerEntityFromSomePlace();
            customer.LastOrderDate = DateTime.UtcNow;
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            TableOperation mergeOperation = TableOperation.Merge(customer);
            table.Execute(mergeOperation);

Insert or Replace Entity

If you’re using the following code with version 1.7 to insert or replace an entity:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-10)
            };
            var serviceContext = cloudTableClient.GetDataServiceContext();
            serviceContext.AttachTo(tableName, customer, null);
            serviceContext.UpdateObject(customer);
            serviceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-10)
            };
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            TableOperation insertOrReplaceOperation = TableOperation.InsertOrReplace(customer);
            table.Execute(insertOrReplaceOperation);

Insert or Merge Entity

If you’re using the following code with version 1.7 to insert or merge an entity:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-10)
            };
            var serviceContext = cloudTableClient.GetDataServiceContext();
            serviceContext.AttachTo(tableName, customer, null);
            serviceContext.UpdateObject(customer);
            serviceContext.SaveChangesWithRetries();

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-10)
            };
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            TableOperation insertOrMergeOperation = TableOperation.InsertOrMerge(customer);
            table.Execute(insertOrMergeOperation);

Entity Batch Operation

As you know, Azure Table Storage supports entity batch transactions to manage multiple entities in a single transaction. Assuming you’re trying to insert some entities in an Azure table using entity batch transaction. If you’re using the following code to perform bulk insert with version 1.7:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-10)
            };
            var serviceContext = cloudTableClient.GetDataServiceContext();
            serviceContext.AddObject(tableName, customer);
            customer = new CustomerEntity()
            {
                FirstName = "Jane",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-5)
            };
            serviceContext.AddObject(tableName, customer);
            customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Doe",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-7)
            };
            serviceContext.AddObject(tableName, customer);
            customer = new CustomerEntity()
            {
                FirstName = "Jane",
                LastName = "Doe",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-3)
            };
            serviceContext.AddObject(tableName, customer);
            serviceContext.SaveChangesWithRetries(SaveChangesOptions.Batch);

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-10)
            };
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            TableBatchOperation batchOperation = new TableBatchOperation();
            batchOperation.Insert(customer);
            customer = new CustomerEntity()
            {
                FirstName = "Jane",
                LastName = "Smith",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-5)
            };
            batchOperation.Insert(customer);
            customer = new CustomerEntity()
            {
                FirstName = "John",
                LastName = "Doe",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-7)
            };
            batchOperation.Insert(customer);
            customer = new CustomerEntity()
            {
                FirstName = "Jane",
                LastName = "Doe",
                LastOrderDate = DateTime.UtcNow.Date.AddDays(-3)
            };
            batchOperation.Insert(customer);
            table.ExecuteBatch(batchOperation);

Fetching Single Entity

If you’re using the following code with version 1.7 to fetch a single entity by PartitionKey and RowKey:

 
            string partitionKey = “<some PartitionKey value>”;
            string rowKey = “<some RowKey value>”;
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var serviceContext = cloudTableClient.GetDataServiceContext();
            IQueryable<CustomerEntity> customerQuery = (from entity in serviceContext.CreateQuery<CustomerEntity>(tableName) where entity.PartitionKey == partitionKey && entity.RowKey == rowKey select entity);
            var returnedCustomer = customerQuery.FirstOrDefault();

You would use something like this with version 2.0 to achieve the same:

 
            string partitionKey = “<some PartitionKey value>”;
            string rowKey = “<some RowKey value>”;
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            TableOperation retrieveOperation = TableOperation.Retrieve<CustomerEntity>(partitionKey, rowKey);
            TableResult retrievedResult = table.Execute(retrieveOperation);
            CustomerEntity fetchedCustomer = retrievedResult.Result as CustomerEntity;

Querying Entities

If you’re using the following code with version 1.7 to fetch entities by say filtering the records on last name attribute of our Customer entity:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            var serviceContext = cloudTableClient.GetDataServiceContext();
            //Specify the filter condition on LastName == 'Smith'
            IQueryable<CustomerEntity> customerQuery = (from entity in serviceContext.CreateQuery<CustomerEntity>(tableName) where entity.LastName == "Smith" select entity);
            var result = customerQuery.ToList();

You would use something like this with version 2.0 to achieve the same:

 
            CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
            CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();
            CloudTable table = cloudTableClient.GetTableReference(tableName);
            //Specify the filter condition on LastName == 'Smith'
            TableQuery<CustomerEntity> query = (new TableQuery<CustomerEntity>()).Where(TableQuery.GenerateFilterCondition("LastName", QueryComparisons.Equal, "Smith"));
            var result = table.ExecuteQuery<CustomerEntity>(query);

Closing Thoughts

As you saw, there’re significant differences between version 1.7 and 2.0 and one need to put some extra thoughts before undertaking the migration however in my opinion the version 2.0 library is much more straight forward to understand and is more intuitive. For example, to create an entity we would use TableOperation.Insert(entity).

Though I did not cover it in this blog post, but you can still use the legacy DataServiceClient approach with version 2.0. Do note that DataServiceClient approach still makes use of WCF services approach. Using TableEntity approach offers significant performance and latency improvements over the WCF Data Services. One thing with DataServiceClient approach is that you’re only allowed to perform single operation per data context. Furthermore the DataServiceClient approach is not available in library for Windows 8. I haven’t tried it myself but it seems we just have to change namespaces under the using section in our source files and everything else should work as is. That would certainly ease the pain in the short run however my personal recommendation is to “take the pill” :) and make use of TableEntity if you can afford it.

Finally, don’t give up on Storage Client Library 1.7 just yet. There’re still some components which depend on 1.7 version. Good example is Windows Azure Diagnostics which still depends on the older version at the time of writing this blog. Good thing is that both version 1.7 and 2.0 can co-exist in a project.

Source Code

You can download the source code for this project from here: Sample Project Source Code

Acknowledgement

I’m thankful to Aymeric Lagier, Richard Conway, and Jai Haridas & Joe Giardino from Windows Azure Storage Team to take time out and reviewing my post.

Summary

The examples I presented in this post are quite basic but hopefully they should give you an idea about how to use the latest version of storage client library. In general, I am quite pleased with the changes the team has done though I wish there was an easier migration path. Please feel free to share your experience with migration exercise by providing comments. This will help me and the readers of this blog immensely. Finally, if you find any issues with this post please let me know and I will try and fix them ASAP.

Happy Coding!


[This is the latest product I'm working on]

Comments

  1. Hi Gaurav,

    Great post – very helpful.

    I’ve got a couple of questions for you (as per our Twitter conversation):

    1. Is there a way to use LINQ to query table storage in the new storage API? I find it surprising if it’s gone – the new method seems to be a lot more verbose and given it has magic strings much less maintainable.

    2. Does the storage library include any logic to help with batch queries such as grouping by partition key and splitting into batches of 100 entities to ensure you meet those constraints of table storage?

    Thanks

    • Thanks Rob. I’m glad you found the posts useful. To answer your questions:

      1. Is there a way to use LINQ to query table storage in the new storage API? I find it surprising if it’s gone – the new method seems to be a lot more verbose and given it has magic strings much less maintainable.

      Yes. You could still use the old way by using TableServiceContext. See the code below for example:

      
                  TableServiceContext serviceContext = new TableServiceContext(cloudTableClient);
                  IQueryable<CustomerEntity> customerQuery = (from entity in serviceContext.CreateQuery<CustomerEntity>(tableName) where entity.LastName == "Smith" select entity);
                  var result1 = customerQuery.ToList();
      

      2. Does the storage library include any logic to help with batch queries such as grouping by partition key and splitting into batches of 100 entities to ensure you meet those constraints of table storage?

      Unfortunately it doesn’t. This is something you would need to do on your own. You could use something like below:

              /// <summary>
              /// Maximum number of entities in a batch (current limit = 100).
              /// </summary>
              private const int maxItemsPerBatch = 100;
      
              /// <summary>
              /// Takes a collection of entities and create entity batches out of it where:
              /// - All items in a batch have same PartitionKey.
              /// - There can be a maximum of 100 entities per batch.
              /// </summary>
              /// <param name="entities">
              /// Collection of <see cref="TableServiceEntity"/>
              /// </param>
              /// <returns>
              /// Collection of collection of <see cref="TableServiceEntity"/> where each internal collection is a batch.
              /// </returns>
              public static IEnumerable<IEnumerable<TableEntity>> SplityEntitiesIntoBatch(IEnumerable<TableEntity> entities)
              {
                  List<List<TableEntity>> batches = new List<List<TableEntity>>();
                  var queryByPartitionKey =
                      from entity in entities
                      group entity by entity.PartitionKey;
                  foreach (var group in queryByPartitionKey)
                  {
                      var entityBatches = SplitBatchIntoBatches(group.ToList());
                      foreach (var item in entityBatches)
                      {
                          batches.Add(item);
                      }
                  }
                  return batches;
              }
      
              /// <summary>
              /// Splits an entity batch into smaller batches if entities count in the input batch is more than 100.
              /// </summary>
              /// <param name="entityBatch">
              /// Collection of <see cref="TableServiceEntity"/> constituting a batch.
              /// </param>
              /// <returns>
              /// Collection of collection of <see cref="TableServiceEntity"/> where each internal collection is a batch.
              /// </returns>
              private static List<List<TableEntity>> SplitBatchIntoBatches(IEnumerable<TableEntity> entityBatch)
              {
                  List<List<TableEntity>> entityBatches = new List<List<TableEntity>>();
                  List<TableEntity> batch = new List<TableEntity>();
                  int skipCount = 0;
                  while (true)
                  {
                      var entitiesInThisBatch = entityBatch.Skip(skipCount).Take(maxItemsPerBatch).ToList();
                      if (entitiesInThisBatch.Count == 0)
                      {
                          break;
                      }
                      entityBatches.Add(entitiesInThisBatch);
                      skipCount += Math.Min(entitiesInThisBatch.Count, maxItemsPerBatch);
                  }
                  return entityBatches;
              }
      

      Hope this helps

  2. This is a very good article, are there any performance benchmarks for TableEntity vs WCF Data Services implementations.

  3. Gaurav,

    You’re postings on 1.7 -> 2.0 migration have been really great & saved me a lot of time! It’s quite remarkable how little documentation and example code with respect to migration there is about Storage 2.0 – it’s such a radical change, you’d think there would be more. And now, with Storage 2.1 out, and LINQ kinda-sorta added back in, there’s a whole new set of changing calls.

    Care to do some tutorials on 2.1? :-)

    Thanks!
    -Dan

  4. Hello, great article! Do you have any info on how the Data Access Layer should now be formed without using TableServiceContext? I am trying to modify the Data Access Layer to not use deprecated classes. But I have several DataContext classes that inherit from the TableServiceContext as that seems to be the standard practice. Do you have any examples of a simple New Data Access class?

Trackbacks

  1. [...] client library 1.7 to 2.0 to manage Windows Azure Table Storage. You can read that post here: http://gauravmantri.com/2012/11/17/storage-client-library-2-0-migrating-table-storage-code/. In this post, I will talk about migrating code from storage client library 1.7 to 2.0 for managing [...]

  2. [...] Gaurav Mantri (an amazing Windows Azure MVP who is always very helpful) has a very good blog series about updating the Storage Client Library, discussing blobs, queues, and table storage. [...]

  3. [...] API in the .NET Storage v2.x library (2.0,  2.1). Gaurav Mantri has also posted on the  Table Service API as part of an excellent series of posts on the Storage v2.0 library. I did a post in 2010 that [...]

Speak Your Mind

*