11

I am trying to update a row in an Azure table based on an Azure Function. I see that the Table bindings can handle an ICollector which has an Add method which will add a row. I also see that you use an IQueryable to read the data.

How do you go about updating a specific row in the data?

I saw in WebJobs something related to InsertOrReplace which is a method of TableOperations but I don't know if or how that comes into play and how to use it with Azure Functions.

3 Answers 3

17

Following is one way you can do this. These steps will get easier with our next release, but for now you need to manually bring in the Azure Storage SDK.

First, follow the steps in the "Package Management" section of this help page to pull in the Azure Storage SDK. You'll be uploading a project.json that looks like this to your function folder:

{
  "frameworks": {
    "net46":{
      "dependencies": {
        "WindowsAzure.Storage": "7.0.0"
      }
    }
   }
}

Note: In the next release we'll automatically include the Azure Storage SDK so you can just use it directly in your code. After you've pulled in the package, you can enter function metadata like the following in the Integrate tab tab Advanced Editor:

{
  "bindings": [
    {
      "name": "input",
      "type": "manualTrigger",
      "direction": "in"
    },
    {
      "name": "table",
      "type": "table",
      "tableName": "test",
      "connection": "<your connection>",
      "direction": "in"
    }
  ]
}

And below is the corresponding code. We're binding to a CloudTable here which lets us read/write entities:

#r "Microsoft.WindowsAzure.Storage"

using System;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;

public static void Run(string input, CloudTable table, TraceWriter log)
{
    TableOperation operation = TableOperation.Retrieve<Person>("AAA", "001");
    TableResult result = table.Execute(operation);
    Person person = (Person)result.Result;

    log.Verbose($"{person.Name} is {person.Status}");

    person.Status = input;
    operation = TableOperation.Replace(person);
    table.Execute(operation);
}

public class Person : TableEntity
{
    public string Name   { get;set; }
    public string Status { get;set; }
}

I used a ManualTrigger for this example, but the table binding will work with whatever trigger you have. With the above set up, I can enter a value in the Run input box of the portal and hit run. The function will query the entity, output its current values, then update using my input.

Other permutations are possible. For example, if you have an entity instance from another binding parameter, you can use the CloudTable in a similar way to update it.

Sign up to request clarification or add additional context in comments.

5 Comments

Seems not to be working since recent update. See: social.msdn.microsoft.com/Forums/en-US/…
Please try updating the package reference for WindowsAzure.Storage from version 4.3 to 7.0.
This seems to now be available by default you just need to add the reference in csx and the using. #r "Microsoft.WindowsAzure.Storage" using Microsoft.WindowsAzure.Storage.Table;
QQ on the <your connection>. Is that a Azure Connection String? DefaultEndpointsProtocol=http;AccountName=myAccount;AccountKey=myKey;
No, the <your connection> should be an app setting name whose value is the connection string
17

With today's bindings, you can set an ETag property to the value * to do an upsert:

[FunctionName("Function1")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    ILogger log,
    [Table("test")] IAsyncCollector<PocoClass> table)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];
    if (name == null)
        return new BadRequestResult();

    await table.AddAsync(new PocoClass { Name = name });
    return new OkObjectResult($"Hello, {name}");
}

public sealed class PocoClass
{
    public string PartitionKey { get; } = "partition";
    public string RowKey { get; } = "row";
    public string ETag { get; } = "*";
    public string Name { get; set; }
}

Comments

3

With the current version of Functions, I was able to make row updates work with declarative bindings. Here is an example with HTTP trigger, which increments a number in Azure Table row.

function.json:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "route": "HttpTriggerTableUpdate/{partition}/{rowkey}"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "table",
      "name": "inputEntity",
      "tableName": "SOTrial",
      "partitionKey": "{partition}",
      "rowKey": "{rowkey}",
      "connection": "my_STORAGE",
      "direction": "in"
    },
    {
      "type": "table",
      "name": "outputEntity",
      "tableName": "SOTrial",
      "partitionKey": "{partition}",
      "rowKey": "{rowkey}",
      "connection": "my_STORAGE",
      "direction": "out"
    }
  ],
  "disabled": false
}

C# function:

#r "Microsoft.WindowsAzure.Storage"

using System;
using System.Net;
using Microsoft.WindowsAzure.Storage.Table;

public class Entity : TableEntity
{
    public int Number {get; set;}
}

public static HttpResponseMessage Run(HttpRequestMessage req, string partition, 
    string rowkey, Entity inputEntity, out Entity outputEntity)
{
    if (inputEntity == null)
        outputEntity = new Entity { PartitionKey = partition, RowKey = rowkey, Number = 1};
    else
    {
        outputEntity = inputEntity;
        outputEntity.Number += 1;
    }

    return req.CreateResponse(HttpStatusCode.OK, $"Done, Number = {outputEntity.Number}");
}

2 Comments

Unfortunately I have not been able to get this technique to work for node.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.