适用于 Azure Functions 的 Azure 表输入绑定

使用 Azure 表输入绑定读取 Azure Cosmos DB for Table 或 Azure 表存储中的表。

有关设置和配置详细信息,请参阅概述。

重要

本文使用选项卡来支持多个版本的 Node.js 编程模型。 v4 模型已正式发布,旨在为 JavaScript 和 TypeScript 开发人员提供更为灵活和直观的体验。 有关 v4 模型工作原理的更多详细信息,请参阅 Azure Functions Node.js 开发人员指南。 要详细了解 v3 和 v4 之间的差异,请参阅迁移指南。

示例

绑定的用法取决于扩展包版本,以及函数应用中使用的 C# 形式,可以是以下形式之一:

独立工作进程类库的已编译 C# 函数在独立于运行时的进程中运行。

选择一个版本以查看模式和版本的示例。

下面的 MyTableData 类表示表中的一行数据:

public class MyTableData : Azure.Data.Tables.ITableEntity
{
    public string Text { get; set; }

    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }
}

以下函数由队列存储触发器启动,它从队列中读取行键,该键用于从输入表中获取行。 表达式 {queueTrigger} 将行键绑定到消息元数据(即消息字符串)。

[Function("TableFunction")]
[TableOutput("OutputTable", Connection = "AzureWebJobsStorage")]
public static MyTableData Run(
    [QueueTrigger("table-items")] string input,
    [TableInput("MyTable", "<PartitionKey>", "{queueTrigger}")] MyTableData tableInput,
    FunctionContext context)
{
    var logger = context.GetLogger("TableFunction");

    logger.LogInformation($"PK={tableInput.PartitionKey}, RK={tableInput.RowKey}, Text={tableInput.Text}");

    return new MyTableData()
    {
        PartitionKey = "queue",
        RowKey = Guid.NewGuid().ToString(),
        Text = $"Output record with rowkey {input} created at {DateTime.Now}"
    };
}

以下由队列触发的函数将前 5 个实体作为 IEnumerable<T> 返回,分区键值设置为队列消息。

[Function("TestFunction")]
public static void Run([QueueTrigger("myqueue", Connection = "AzureWebJobsStorage")] string partition,
    [TableInput("inTable", "{queueTrigger}", Take = 5, Filter = "Text eq 'test'", 
    Connection = "AzureWebJobsStorage")] IEnumerable<MyTableData> tableInputs,
    FunctionContext context)
{
    var logger = context.GetLogger("TestFunction");
    logger.LogInformation(partition);
    foreach (MyTableData tableInput in tableInputs)
    {
        logger.LogInformation($"PK={tableInput.PartitionKey}, RK={tableInput.RowKey}, Text={tableInput.Text}");
    }
}

Filter 和 Take 属性用于限制返回的实体数。

以下示例显示了一个 HTTP 触发函数,该函数返回表存储中指定分区中的 person 对象列表。 在此示例中,分区键将从 http 路由中提取,表名和连接将从函数设置中提取。

public class Person {
    private String PartitionKey;
    private String RowKey;
    private String Name;

    public String getPartitionKey() { return this.PartitionKey; }
    public void setPartitionKey(String key) { this.PartitionKey = key; }
    public String getRowKey() { return this.RowKey; }
    public void setRowKey(String key) { this.RowKey = key; }
    public String getName() { return this.Name; }
    public void setName(String name) { this.Name = name; }
}

@FunctionName("getPersonsByPartitionKey")
public Person[] get(
        @HttpTrigger(name = "getPersons", methods = {HttpMethod.GET}, authLevel = AuthorizationLevel.FUNCTION, route="persons/{partitionKey}") HttpRequestMessage<Optional<String>> request,
        @BindingName("partitionKey") String partitionKey,
        @TableInput(name="persons", partitionKey="{partitionKey}", tableName="%MyTableName%", connection="MyConnectionString") Person[] persons,
        final ExecutionContext context) {

    context.getLogger().info("Got query for person related to persons with partition key: " + partitionKey);

    return persons;
}

TableInput 注释还可以从请求的 json 正文中提取绑定,如下面的示例所示。

@FunctionName("GetPersonsByKeysFromRequest")
public HttpResponseMessage get(
        @HttpTrigger(name = "getPerson", methods = {HttpMethod.GET}, authLevel = AuthorizationLevel.FUNCTION, route="query") HttpRequestMessage<Optional<String>> request,
        @TableInput(name="persons", partitionKey="{partitionKey}", rowKey = "{rowKey}", tableName="%MyTableName%", connection="MyConnectionString") Person person,
        final ExecutionContext context) {

    if (person == null) {
        return request.createResponseBuilder(HttpStatus.NOT_FOUND)
                    .body("Person not found.")
                    .build();
    }

    return request.createResponseBuilder(HttpStatus.OK)
                    .header("Content-Type", "application/json")
                    .body(person)
                    .build();
}

下面的示例使用筛选器在 Azure 表中查询具有特定名称的人员,并将可能的匹配项数目限制为 10 个结果。

@FunctionName("getPersonsByName")
public Person[] get(
        @HttpTrigger(name = "getPersons", methods = {HttpMethod.GET}, authLevel = AuthorizationLevel.FUNCTION, route="filter/{name}") HttpRequestMessage<Optional<String>> request,
        @BindingName("name") String name,
        @TableInput(name="persons", filter="Name eq '{name}'", take = "10", tableName="%MyTableName%", connection="MyConnectionString") Person[] persons,
        final ExecutionContext context) {

    context.getLogger().info("Got query for person related to persons with name: " + name);

    return persons;
}

以下示例显示了使用队列触发器读取单个表行的表输入绑定。 该绑定指定一个 partitionKey 和一个 rowKey。 rowKey 值“{queueTrigger}”指示行键来自队列消息字符串。

import { app, input, InvocationContext } from '@azure/functions';

const tableInput = input.table({
    tableName: 'Person',
    partitionKey: 'Test',
    rowKey: '{queueTrigger}',
    connection: 'MyStorageConnectionAppSetting',
});

interface PersonEntity {
    PartitionKey: string;
    RowKey: string;
    Name: string;
}

export async function storageQueueTrigger1(queueItem: unknown, context: InvocationContext): Promise<void> {
    context.log('Node.js queue trigger function processed work item', queueItem);
    const person = <PersonEntity>context.extraInputs.get(tableInput);
    context.log('Person entity name: ' + person.Name);
}

app.storageQueue('storageQueueTrigger1', {
    queueName: 'myqueue-items',
    connection: 'MyStorageConnectionAppSetting',
    extraInputs: [tableInput],
    handler: storageQueueTrigger1,
});
const { app, input } = require('@azure/functions');

const tableInput = input.table({
    tableName: 'Person',
    partitionKey: 'Test',
    rowKey: '{queueTrigger}',
    connection: 'MyStorageConnectionAppSetting',
});

app.storageQueue('storageQueueTrigger1', {
    queueName: 'myqueue-items',
    connection: 'MyStorageConnectionAppSetting',
    extraInputs: [tableInput],
    handler: (queueItem, context) => {
        context.log('Node.js queue trigger function processed work item', queueItem);
        const person = context.extraInputs.get(tableInput);
        context.log('Person entity name: ' + person.Name);
    },
});

下面的函数使用队列触发器读取单个表行作为函数的输入。

在此示例中,绑定配置为表的 partitionKey 指定一个显式值,并使用了一个要传递给 rowKey 的表达式。 rowKey 表达式 {queueTrigger} 指示行键来自队列消息字符串。

function.json 中的绑定配置:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "MyQueueItem",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "PersonEntity",
      "type": "table",
      "tableName": "Person",
      "partitionKey": "Test",
      "rowKey": "{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    }
  ],
  "disabled": false
}

run.ps1 中的 PowerShell 代码:

param($MyQueueItem, $PersonEntity, $TriggerMetadata)
Write-Host "PowerShell queue trigger function processed work item: $MyQueueItem"
Write-Host "Person entity name: $($PersonEntity.Name)"

下面的函数使用 HTTP 触发器读取单个表行作为函数的输入。

在此示例中,绑定配置为表的 partitionKey 指定一个显式值,并使用了一个要传递给 rowKey 的表达式。 rowKey 表达式 {id} 指示行键来自请求中路由的 {id} 部分。

import json
import azure.functions as func

app = func.FunctionApp()

@app.route(route="messages/{id}")
@app.table_input(arg_name="messageJSON",
                 connection="AzureWebJobsStorage",
                 table_name="messages",
                 row_key='{id}',
                 partition_key="message")
def table_in_binding(req: func.HttpRequest, messageJSON):
    message = json.loads(messageJSON)
    return func.HttpResponse(f"Table row: {messageJSON}")

使用这种简单绑定,无法以编程方式处理没有找到行键 ID 的行。 有关更精细的数据选择,请使用存储 SDK。

特性

进程内和独立工作进程 C# 库使用特性来定义函数。 C# 脚本改用 function.json 配置文件,如 C# 脚本指南中所述。

在 C# 类库中,TableInputAttribute 支持以下属性:

Attribute 属性 说明
TableName 表的名称。
PartitionKey 可选。 要读取的表实体的分区键。
RowKey 可选。 要读取的表实体的行键。
拿 可选。 要读取到 IEnumerable<T> 的最大实体数。 无法与 RowKey 一起使用。
滤波器 可选。 要读取到 IEnumerable<T> 的实体的 OData 筛选器表达式。 无法与 RowKey 一起使用。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接。

批注

在 Java 函数运行时库中,对其值将来自表存储的参数使用 @TableInput 注释。 可以将此注释与本机 Java 类型、POJO 或使用了 Optional<T> 的可为 null 的值一起使用。 此批注支持以下元素:

元素 说明
名称 表示函数代码中的表或实体的变量的名称。
tableName 表的名称。
partitionKey 可选。 要读取的表实体的分区键。
rowKey 可选。 要读取的表实体的行键。
拿 可选。 要读取的实体的最大数目。
滤波器 可选。 表输入的 OData 筛选表达式。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接。

配置

下表说明了可以在传递给 options 方法的 input.table() 对象上设置的属性。

properties 说明
tableName 表的名称。
partitionKey 可选。 要读取的表实体的分区键。
行键 可选。 要读取的表实体的行键。 不能与 take 或 filter 一起使用。
拿 可选。 要返回的实体的最大数目。 无法与 rowKey 一起使用。
滤波器 可选。 用于从表中返回实体的 OData 筛选器表达式。 无法与 rowKey 一起使用。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接。

配置

下表解释了在 function.json 文件中设置的绑定配置属性。

“function.json”属性 说明
类型 必须设置为 table。 在 Azure 门户中创建绑定时,会自动设置此属性。
方向 必须设置为 in。 在 Azure 门户中创建绑定时,会自动设置此属性。
名字 表示函数代码中的表或实体的变量的名称。
tableName 表的名称。
partitionKey 可选。 要读取的表实体的分区键。
行键 可选。 要读取的表实体的行键。 不能与 take 或 filter 一起使用。
拿 可选。 要返回的实体的最大数目。 无法与 rowKey 一起使用。
滤波器 可选。 用于从表中返回实体的 OData 筛选器表达式。 无法与 rowKey 一起使用。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接。

在本地开发时,请将应用程序设置添加到 集合的 Values。

连接

该 connection 属性在应用设置中被设置为键,返回函数运行时用于连接扩展所用存储账户的值。 连接属性设置的值取决于连接类型:

  • 管理身份连接:该 connection 属性是由 <CONNECTION_NAME_PREFIX> 一组设置共享的,这些设置共同定义了基于身份的连接与存储账户。 更多信息请参见 定义身份连接。
  • 密钥保管库 引用:connection属性设置返回一个 Azure 密钥保管库 引用,指向该 连接字符串 中心维护的位置。 更多信息请参见定义 密钥保管库 连接。
  • App Configuration 引用:connection属性设置返回一个 Azure 应用程序配置 引用,返回一个 连接字符串 或 密钥保管库 引用。 更多信息请参见连接文章中的 Azure 应用程序配置。
  • Connection string:属性设置返回connection实际存储账户的连接字符串。 由于连接字符串包含共享的秘密密钥,你应尽量考虑使用管理身份连接。 更多信息请参见定义连接。

欲了解更多关于绑定连接的信息,请参见 Azure Functions 中的 Manage connection 。 若要获取连接字符串,请按照 管理存储帐户访问密钥中显示的步骤进行操作。

当你设置为 connection 一个键或前缀命名 AzureWebJobsStorage ,或者设置为空字符串时,绑定扩展会使用默认的主机存储账户。 更多信息请参见 优化存储性能。

使用情况

绑定的用法取决于扩展包版本,以及函数应用中使用的 C# 形式,可以是以下形式之一:

独立工作进程类库的已编译 C# 函数在独立于运行时的进程中运行。

选择一个版本以查看模式和版本的使用情况详细信息。

如果使用单个表实体,可将 Azure 表输入绑定绑到以下类型:

类型 说明
实现 ITableEntity 的 JSON 可序列化类型 Functions 会尝试将实体反序列化为普通的旧 CLR 对象 (POCO) 类型。 该类型必须实现 ITableEntity 或具有字符串 RowKey 属性和字符串 PartitionKey 属性。
TableEntity1 作为类似于字典的类型的实体。

如果使用查询中的多个实体,可将 Azure 表输入绑定绑到以下类型:

类型 说明
IEnumerable<T> 其中 T 实现 ITableEntity 查询返回的实体的枚举。 每个条目表示一个实体。 类型 T 必须实现 ITableEntity 或具有字符串 RowKey 属性和字符串 PartitionKey 属性。
TableClient1 连接到表的客户端。 这提供了对表处理的充分控制,如果连接具有足够的权限,则可用于写入容器。

1 若要使用这些类型,需要引用 Microsoft.Azure.Functions.Worker.Extensions.Tables 1.2.0 或更高版本以及 SDK 类型绑定的常见依赖项。

使用 TableInput 特性可以访问触发了函数的表行。

使用 context.extraInputs.get() 获取输入行数据。

数据将传递给 function.json 文件中 name 键所指定的输入参数。 通过指定 partitionKey 和 rowKey,可以筛选到特定记录。

表数据将作为 JSON 字符串传递给函数。 通过调用 json.loads 反序列化消息,如输入示例所示。

有关具体使用情况的详细信息,请参阅示例。

后续步骤