Creating an Upsert with Azure Functions for a Table Storage Entity

|  Posted: February 1, 2017  |  Categories: Microsoft Azure

Azure Functions are great when you need small pieces of code, or “functions” in the cloud. You also get a lot of Templates with sample code to speed up the development even more. For most scenarios, this is sufficient but for more advanced scenarios however, there is not always a lot of documentation.

The “HttpPOST(CRUD)-C#” template for example, creates a C# Function that adds entities to a Storage Table when it receives a HTTP request. That is great but what if an entity already is stored in the Storage Table? In that case you probably want to update the entity in the Storage Table. This is what becomes called Upserts and in this article we’ll describe how you can achieve that with Azure Functions.

In the following section is described how to modify the generated code from the “HttpPOST(CRUD)-C#” Template, so that the function adds new orders to a Storage Table and modifies the order when it already exists in the Storage Table.

Creating Azure Functions in Visual Studio

You can use the Azure Portal to create Azure functions but in this demo Visual Studio is used to develop the function. See the following blog post how to install the Azure Functions Visual Studio Tools Preview:
https://buildazure.com/2016/12/14/azure-functions-visual-studio-tools-preview/

Once the Visual Studio Tools for Azure Functions Preview are installed, you can easily create a new Azure Functions project within Visual Studio 2015. In the New Project dialog, it’s located under Visual C# in the Cloud section.

Azure Functions New Project screen

To add a New Azure Function to the project:

  • Right-click on the Project within the Solution Explorer window
  • Click on Add, then New Azure Function

Azure Functions creating a new function

Within the New Azure Function dialog, select the “HttpPOST(CRUD)-C#” Azure Function template from the list. This will create a C# Function that adds entities to a Storage Table when it receives a HTTP request.

Azure Functions HttpPOST(CRUD)-C#

The files created for a new Azure Functions project are similar when you would create an Azure Function through the Azure Portal.

Azure Functions Files created

Modify the generated bindings in the function.json file. Use a variable named OrderStorage for the connection name and add an extra table parameter to be able to search and update in Azure Table Storage.

{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"post"
],
"authLevel": "function"
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "table",
"name": "outTable",
"tableName": "Orders",
"connection": "OrderStorage",
"direction": "out"
},
{
"name": "table",
"type": "table",
"connection": "OrderStorage",
"tableName": "Orders",
"direction": "in"
}
],
"disabled": false
}

In the appsettings.json file add the connection string to your Azure storage account.

{
  "IsEncrypted": false,
  "Values": {
    "OrderStorage": "DefaultEndpointsProtocol=https;AccountName=myAccountName;AccountKey=myAccountKey"
  }
}

In the run.csx file, add an extra table parameter in the function to be able to search for orders.  Then add the extra code to retrieve and update the order.

#r "Microsoft.WindowsAzure.Storage"

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

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ICollector<Order> outTable, CloudTable table, TraceWriter log)
{
    dynamic data = await req.Content.ReadAsAsync<object>();

    string orderId = data?.OrderId;

    TableOperation operation = TableOperation.Retrieve<Order>("Orders", orderId);
    TableResult result = table.Execute(operation);

    if (result.Result != null)
    {
        Order order = (Order)result.Result;
        order.Name = data?.customer.Name;
        order.City = data?.customer.City;
        order.Brand = data?.item.Brand;
        order.ProductType = data?.item.ProductType;
        order.Article = data?.item.Article;
        order.Amount = data?.item.Amount;

        operation = TableOperation.Replace(order);
        table.Execute(operation);
    }
    else
    {
        outTable.Add(new Order()
        {
            PartitionKey = "Orders",
            RowKey = orderId,
            Name = data?.customer.Name,
            City = data?.customer.City,
            Brand = data?.item.Brand,
            ProductType = data?.item.ProductType,
            Article = data?.item.Article,
            Amount = data?.item.Amount
        });
    }

    return req.CreateResponse(HttpStatusCode.Created);
}

public class Order : TableEntity
{   
    public string Name { get; set; }
    public string City { get; set; }
    public string Brand { get; set; }
    public string ProductType { get; set; }
    public string Article { get; set; }
    public int Amount { get; set; }
}

Local Debugging

Azure Functions projects can be run on the local development machine. This is great because now you can set break points in Visual Studio and debug the Azure Function locally.

Azure Functions debug the function

When you try to run the Azure Project and the bindings in the function.json file are not correct, you get an error message that the Connection string is missing.

Azure Functions error message

Also note that when the connection string of your Azure storage account is not correct, you get another error message that the initialization of the ScripHost failed when you try to run the Azure Function.

Azure Functions initialization failed

When all settings are correct, the Azure Function can be tested with a tool like Postman.

Azure Functions testing using postman

After the HTTP request is posted use the Azure Storage Explorer, tool to see it the order is added and also modified in Table Storage.

Azure Functions azure storage explorer

Conclusion

I really like Azure Functions because you get a lot of functionality out of the box. However, the part I didn’t like was developing in the Azure Portal, but this is now solved by using the Visual Studio Tools. The only thing I now wish for, is a little bit more documentation and then Azure Functions is really awesome!

Author: Tomasso Groenendijk

Tomasso Groenendijk is a senior Integration consultant at Motion10 and has over 15 years of experience in software development and software design. He specializes in applications integration with a strong interest in Windows Azure cloud platform. In 2014, 2015 and 2016 Tomasso was awarded with the Microsoft Integration MVP award. He is an active contributor to the BizTalk community through his work on MSDN forums, TechNet Wiki and his blog.

One Platform Operations, Monitoring and Analytics Software
BizTalk360

microsoft biztalk

Learn more

Over 500 customers across 30+ countries depend on BizTalk360

ServiceBus360

Azure service bus

Learn more

Start managing your Azure Service Bus namespaces in minutes

One Platform - Operations, Monitoring and Analytics Software
BizTalk360

microsoft biztalk

Learn more

Over 500 customers across 30+ countries depend on BizTalk360

One Platform - Operations, Monitoring and Analytics Software
ServiceBus360

Azure service bus

Learn more

Start managing your Azure Service Bus namespaces in minutes

Back to Top