What’s new in the Azure Functions Tables extension for .NET **Beta**

Josh Love

Previously, the Azure Tables bindings for .NET were available as part of the Microsoft.Azure.WebJobs.Extensions.Storage package (version 4 and earlier). Version 5 of the storage extensions package no longer contains the Tables bindings. Instead, the Tables bindings are available in a new package called Microsoft.Azure.WebJobs.Extensions.Tables, which is now in beta. Like the other new Azure Functions extensions for Storage, Event Hubs, and Service Bus, the new Tables extension supports integration with Azure.Identity.

Configuration

To authenticate, provide an endpoint, a connection string, or a shared key. This configuration is set in the Application settings section of your function app in the Azure portal. For more information on configuring application settings for Functions apps, see Manage your function app.

Identity

To use Azure Active Directory authentication, you must provide an endpoint. You can optionally provide additional credential information. To use Managed Identity, specify the following settings:

Name Value
MyConnection__endpoint https://...table.core.windows.net
MyConnection__credential managedidentity
MyConnection__clientId {user-assigned client id}

If no credential information is provided, the DefaultAzureCredential is used.

Connection string

To use connection string authentication, assign the connection string value directly to the connection setting. You can do one of the following things:

  • Define a custom connection setting. For example, MyConnection.
  • Use the default connection setting, AzureWebJobsStorage.
Name Value
MyConnection DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net

Shared key

To use shared key authentication, the endpoint, account key, and account name are required:

Name Value
MyConnection__endpoint https://...table.core.windows.net
MyConnection__credential__accountName {account name}
MyConnection__credential__accountKey {account key}

Usage

Unlike some of the other Azure Functions extensions, the Tables Functions extension doesn’t support triggering. It supports reading, updating, and writing entries to a table; you’ll need the function to be triggered by something else. In the following examples, we demonstrate using an HttpTrigger in our functions. Also note that unlike the previous version of the Tables bindings, there are no longer separate attributes for input and output binding. Instead, the behavior is dependent on the arguments passed to the [Table] attribute.

Input binding

When binding to a single entity, you must specify the table name, partition key, and row key in the [Table] attribute.

Binding using TableEntity

public class InputSingle
{
    [FunctionName("InputSingle")]
    public static void Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "GET")] HttpRequest request,
        [Table("MyTable", "<PartitionKey>", "<RowKey>")] TableEntity entity, ILogger log)
    {
        log.LogInformation($"PK={entity.PartitionKey}, RK={entity.RowKey}, Text={entity["Text"]}");
    }
}

Binding using a custom model

When you use a custom model, the binding is based on the property name and type of the members. Because PartitionKey and RowKey are always included in a table entity, you’re able to bind to them as named properties. Additionally, you can implement ITableEntity, which makes it easier to define the available properties correctly. For example:

public class MyEntity : ITableEntity
{
    // ITableEntity properties
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }

    // custom property
    public string Text { get; set; }
}
public class InputSingleModel
{
    [FunctionName("InputSingleModel")]
    public static void Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "GET")] HttpRequest request,
        [Table("MyTable", "<PartitionKey>", "<RowKey>")] MyEntity entity, ILogger log)
    {
        log.LogInformation($"PK={entity.PartitionKey}, RK={entity.RowKey}, Text={entity.Text}");
    }
}

It’s also possible to define a complex property. For example, see the following MyModel-typed property:

public class MyEntity
{
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public string Text { get; set; }
    public MyModel Model { get; set; }
}

With this model defined, the extension will attempt to deserialize the table entities “Model” JSON into the strongly typed MyModel object.

Update entity

You can also update entities when using the input binding. When updating an entity, you aren’t able to modify the RowKey or PartitionKey. You can, however, update any other attribute of the entity. If your function modifies the entity, the extension will attempt to update the entity in the table.

Output binding

To use the output binding, specify only the table name in the [Table] attribute.

Create a new entity using TableEntity

public class OutputSingle
{
    [FunctionName("OutputSingle")]
    public static void Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "GET")] HttpRequest request,
        [Table("MyTable")] out TableEntity entity)
    {
        entity = new TableEntity("<PartitionKey>", "<RowKey>")
        {
            ["Text"] = "Hello"
        };
    }
}

Create a new entity using a custom model

public class MyEntity
{
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public string Text { get; set; }
}
public class OutputSingleModel
{
    [FunctionName("OutputSingleModel")]
    public static void Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "GET")] HttpRequest request,
        [Table("MyTable")] out MyEntity entity)
    {
        entity = new MyEntity()
        {
            PartitionKey = "<PartitionKey>",
            RowKey = "<RowKey>",
            Text = "Hello"
        };
    }
}

Conclusion

More examples, including binding to multiple entities, can be found in the project’s README. We hope you’ll try out the new extensions and provide feedback!

0 comments

Comments are closed. Login to edit/delete your existing comments