Anthony Chu Contact Me

Updating and Deleting Table Storage Entities with Azure Functions (C# and JavaScript)

Saturday, February 11, 2017

Inserting entities into Table Storage from Azure Functions is a breeze with the Azure Table Storage output bindings. However, the bindings don't directly support updating and deleting entities (yet).

But it's actually pretty easy to support updates and deletes. In C#, this can be done using the Table Storage output binding with a CloudTable parameter. In Node/JavaScript, we can use the azure-storage NPM package.

Our Example

The example we'll be using is fairly straight forward. We'll be updating a table named "items". Each item has an id and a value. We'll use the id as both the partition key and row key for each entity in Table Storage.

The table

C#

Updating an entity

The update function has HTTP trigger and output bindings. It also has a Table Storage output binding that looks exactly like one used to insert entities into a table. Here's the function.json:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "item",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "put"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "table",
      "name": "outputTable",
      "tableName": "items",
      "connection": "StorageConnectionString",
      "direction": "out"
    }
  ],
  "disabled": false
}

But instead of using an ICollector as the outputTable parameter, we'll instead use a CloudTable. This gives us a reference to the table as a CloudTable object from the Table Storage SDK and we have full control over what we can do to the table. Here is the run.csx:

#r "Microsoft.WindowsAzure.Storage"
using Microsoft.WindowsAzure.Storage.Table;
using System.Net;

public static async Task<HttpResponseMessage> Run(Item item, CloudTable outputTable, TraceWriter log)
{
    item.PartitionKey = item.id;
    item.RowKey = item.id;
    item.ETag = "*";

    var operation = TableOperation.Replace(item);
    await outputTable.ExecuteAsync(operation);

    return new HttpResponseMessage(HttpStatusCode.NoContent);
}

public class Item: TableEntity
{
    public string id { get; set; }
    public string value { get; set; }
}

In order to use CloudTable, we need a reference to the Table Storage SDK at the top of the file. All we have to do is create a Replace operation and execute it on the table. By default, the SDK enforces optimistic concurrency via ETags. By setting the ETag to *, we're implementing a "last-write-wins" strategy.

Deleting an entity

Deleting is almost exactly the same...

#r "Microsoft.WindowsAzure.Storage"
using Microsoft.WindowsAzure.Storage.Table;
using System.Net;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, CloudTable outputTable, TraceWriter log)
{
    string id = req.GetQueryNameValuePairs()
        .First(q => string.Compare(q.Key, "id", true) == 0)
        .Value;

    var item = new TableEntity(id, id)
    {
        ETag = "*"
    };
    var operation = TableOperation.Delete(item);
    await outputTable.ExecuteAsync(operation);

    return req.CreateResponse(HttpStatusCode.NoContent);
}

JavaScript

Table Storage Node SDK

Before we can update and delete entities with JavaScript, we have to install the Azure Table Storage Node SDK to our function app.

We can do this by dropping this package.json file into our function app root (D:\home\site\wwwroot):

{
  "name": "tableupdatedelete",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "azure-storage": "^2.0.0"
  }
}

Azure Functions currently doesn't run npm install automatically. We need to open up a console in Kudu, navigate to wwwroot, and run npm install to download the SDK. By installing it to the function app root, the packages are available to all JavaScript functions in the app. More details on how to use NPM packages can be found here.

Kudu console

Updating an entity

For our JavaScript update function, we just have the HTTP trigger and output bindings. There's no need for a Table Storage output binding because we won't be using it.

We have our storage account connection in an app setting named StorageConnectionString. We can use this in our function as an environment variable.

let azure = require('azure-storage');

module.exports = function (context, req) {
    let item = req.body;
    item.PartitionKey = item.id;
    item.RowKey = item.id;

    let connectionString = process.env.StorageConnectionString;
    let tableService = azure.createTableService(connectionString);
    tableService.replaceEntity('items', item, (error, result, response) => {
        let res = {
            statusCode: error ? 400 : 204,
            body: null
        };
        context.done(null, res);
    });
};

Like the C# version, the JavaScript code is straight-forward. The JavaScript SDK doesn't enforce optimistic concurrency by default, so there's no need to worry about ETags here.

Deleting an entity

The delete code works just like the update one:

let azure = require('azure-storage');

module.exports = function (context, req) {
    let id = req.query.id;

    let connectionString = process.env.StorageConnectionString;
    let tableService = azure.createTableService(connectionString);

    let item = {
        PartitionKey: id,
        RowKey: id
    };

    tableService.deleteEntity('items', item, (error, response) => {
        let res = {
            statusCode: error ? 400 : 204,
            body: null
        };
        context.done(null, res);
    });
};

Source Code

The source for the example function app can be found here: https://github.com/anthonychu/azure-functions-update-delete-table-storage