Using the Table Storage Upsert (Insert or Replace)

I just implemented the new Upsert functionality introduced in the Azure SDK 1.6 and wanted to document the solution as I missed one detail that kept me struggling for a while – hopefully this post can help someone else avoid it!

My intent with this change was to replace another update method that first checked to see if the entity already existed, and then either added the new entity or updated the existing one. Upsert will cut down my storage transactions for updates in half as it only executes one request per update. It will also boost performance for the same reason.

Step 1:
Make sure that a specific version header is sent in the REST requests to the storage service. I have a static method that creates a TableServiceContext that I updated with one row (line 10):

        public static TableServiceContext CreateContext()
        {
            var context = new TableServiceContext(BaseAddress, Credentials)
            {
                IgnoreResourceNotFoundException = true // FirstOrDefault() will return null if no match, instead of 404 exception
            };

            // Add specific header to support Upsert
            // TODO: Remove when Azure supports this by default
            context.SendingRequest += (sender, args) => (args.Request).Headers["x-ms-version"] = "2011-08-18";

            return context;
        }

Step 2:
Use the AttachTo method combined with UpdateObject and the ReplaceOnUpdate option for the SaveChanges method to execute the upsert (I have a generic class with the table storage methods):

        public void AddOrReplace(T obj)
        {
            _tableServiceContext.AttachTo(_tableName, obj);
            _tableServiceContext.UpdateObject(obj);
            _tableServiceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);
        }

Note: I Already had an Update method that used the same code but with the following slightly different AttachTo call (the last asterisk parameter). This caused a ResourceNotFound error when saving changes and it took me a while to find and fix this error.

_tableServiceContext.AttachTo(_tableName, obj, "*");

That’s it!

Advertisements

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