你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

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

使用 Azure 表输出绑定将实体写入 Azure Cosmos DB for TableAzure 表存储中的表。

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

注意

此输出绑定仅支持在表中创建新实体。 如果需要从函数代码更新现有实体,请改为直接使用 Azure 表 SDK。

重要

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

示例

目前没有支持这个绑定的 Go。

可使用以下 C# 模式之一来创建 C# 函数:

  • 独立辅助角色模型:编译的 C# 函数,该函数在独立于运行时的工作进程中运行。 需要独立工作进程才能支持在 LTS 和非 LTS 版 .NET 和 .NET Framework 上运行的 C# 函数。 独立工作进程函数的扩展使用 Microsoft.Azure.Functions.Worker.Extensions.* 命名空间。
  • 进程内模型:编译的 C# 函数,该函数在与 Functions 运行时相同的进程中运行。 在此模型的变体中,可以使用 C# 脚本运行 Functions,该脚本主要用于 C# 门户编辑。 进程内函数的扩展使用 Microsoft.Azure.WebJobs.Extensions.* 命名空间。

下面的 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; }
}

以下函数由队列存储触发器启动,可将新 MyDataTable 实体写入名为 OutputTable 的表。

[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}"
    };
}

以下示例演示了使用 HTTP 触发器写入单个表行的 Java 函数。

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; }
}

public class AddPerson {

    @FunctionName("addPerson")
    public HttpResponseMessage get(
            @HttpTrigger(name = "postPerson", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION, route="persons/{partitionKey}/{rowKey}") HttpRequestMessage<Optional<Person>> request,
            @BindingName("partitionKey") String partitionKey,
            @BindingName("rowKey") String rowKey,
            @TableOutput(name="person", partitionKey="{partitionKey}", rowKey = "{rowKey}", tableName="%MyTableName%", connection="MyConnectionString") OutputBinding<Person> person,
            final ExecutionContext context) {

        Person outPerson = new Person();
        outPerson.setPartitionKey(partitionKey);
        outPerson.setRowKey(rowKey);
        outPerson.setName(request.getBody().get().getName());

        person.setValue(outPerson);

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

以下示例演示了使用 HTTP 触发器写入多个表行的 Java 函数。

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; }
}

public class AddPersons {

    @FunctionName("addPersons")
    public HttpResponseMessage get(
            @HttpTrigger(name = "postPersons", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION, route="persons/") HttpRequestMessage<Optional<Person[]>> request,
            @TableOutput(name="person", tableName="%MyTableName%", connection="MyConnectionString") OutputBinding<Person[]> persons,
            final ExecutionContext context) {

        persons.setValue(request.getBody().get());

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

以下示例显示写入多个表实体的表输出绑定。

import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions';

const tableOutput = output.table({
    tableName: 'Person',
    connection: 'MyStorageConnectionAppSetting',
});

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

export async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
    const rows: PersonEntity[] = [];
    for (let i = 1; i < 10; i++) {
        rows.push({
            PartitionKey: 'Test',
            RowKey: i.toString(),
            Name: `Name ${i}`,
        });
    }
    context.extraOutputs.set(tableOutput, rows);
    return { status: 201 };
}

app.http('httpTrigger1', {
    methods: ['POST'],
    authLevel: 'anonymous',
    extraOutputs: [tableOutput],
    handler: httpTrigger1,
});
const { app, output } = require('@azure/functions');

const tableOutput = output.table({
    tableName: 'Person',
    connection: 'MyStorageConnectionAppSetting',
});

app.http('httpTrigger1', {
    methods: ['POST'],
    authLevel: 'anonymous',
    extraOutputs: [tableOutput],
    handler: async (request, context) => {
        const rows = [];
        for (let i = 1; i < 10; i++) {
            rows.push({
                PartitionKey: 'Test',
                RowKey: i.toString(),
                Name: `Name ${i}`,
            });
        }
        context.extraOutputs.set(tableOutput, rows);
        return { status: 201 };
    },
});

以下示例演示如何通过一个函数向表中写入多个实体。

function.json 中的绑定配置:

{
  "bindings": [
    {
      "name": "InputData",
      "type": "manualTrigger",
      "direction": "in"
    },
    {
      "tableName": "Person",
      "connection": "MyStorageConnectionAppSetting",
      "name": "TableBinding",
      "type": "table",
      "direction": "out"
    }
  ],
  "disabled": false
}

run.ps1 中的 PowerShell 代码:

param($InputData, $TriggerMetadata)

foreach ($i in 1..10) {
    Push-OutputBinding -Name TableBinding -Value @{
        PartitionKey = 'Test'
        RowKey = "$i"
        Name = "Name $i"
    }
}

下面的示例演示如何使用表存储输出绑定。 通过为 tablenametableName 分配值,在 function.json 中配置 partitionKey 绑定:

以下函数为 rowKey 值生成唯一 UUI,并将消息持久保存在表存储中。

import logging
import uuid
import json
import azure.functions as func

app = func.FunctionApp()

@app.route(route="table_out_binding")
@app.table_output(arg_name="message",
                  connection="AzureWebJobsStorage",
                  table_name="messages")
def table_out_binding(req: func.HttpRequest, message: func.Out[str]):
    row_key = str(uuid.uuid4())
    data = {
        "Name": "Output binding message",
        "PartitionKey": "message",
        "RowKey": row_key
    }
    table_json = json.dumps(data)
    message.set(table_json)
    return table_json

特性

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

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

Attribute 属性 说明
TableName 要向其写入的表的名称。
PartitionKey 要写入的表实体的分区键。
RowKey 要写入的表实体的行键。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接

批注

Java 函数运行时库中,对参数使用 TableOutput 注释以将值写入到表中。 该特性支持以下元素:

元素 说明
名字 在函数代码中使用的、表示表或实体的变量名称。
dataType 定义 Functions 运行时应如何处理参数值。 有关详细信息,请参阅 dataType
tableName 要向其写入的表的名称。
partitionKey 要写入的表实体的分区键。
行键 要写入的表实体的行键。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接

配置

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

properties 说明
tableName 要向其写入的表的名称。
partitionKey 要写入的表实体的分区键。
行键 要写入的表实体的行键。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接

配置

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

“function.json”属性 说明
类型 必须设置为 table。 在 Azure 门户中创建绑定时,会自动设置此属性。
方向 必须设置为 out。 在 Azure 门户中创建绑定时,会自动设置此属性。
名字 在函数代码中使用的、表示表或实体的变量名称。 设置为 $return 可引用函数返回值。
tableName 要向其写入的表的名称。
partitionKey 要写入的表实体的分区键。
行键 要写入的表实体的行键。
连接 指定如何连接到表服务的应用设置或设置集合的名称。 请参阅连接

在本地开发时,请将应用程序设置添加到 集合的 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 可序列化类型 函数尝试将普通的旧 CLR 对象 (POCO) 类型序列化为实体。 该类型必须实现 [ITableEntity] 或具有字符串 RowKey 属性和字符串 PartitionKey 属性。

如果希望函数写入多个实体,Azure 表输出绑定可以绑定到以下类型:

类型 说明
T[],其中 T 是单个实体类型之一 包含多个实体的数组。 每个条目表示一个实体。

对于其他输出方案,请直接从 Azure.Data.Tables 创建和使用 TableClient 和其他类型的 。 有关使用依赖项注入从 Azure SDK 创建客户端类型的示例,请参阅 “注册 Azure 客户端 ”。

有两个选项可用于使用 TableStorageOutput 注释从函数来输出表存储行:

选项 说明
返回值 通过将注释应用于函数本身,函数的返回值将持久保存为表存储行。
命令性 若要显式设置表行,请将注释应用于 OutputBinding<T> 类型的特定参数,其中 T 包括 PartitionKeyRowKey 属性。 可以通过实现 ITableEntity 或继承 TableEntity 来随附这些属性。

通过返回值或使用 context.extraOutputs.set() 设置输出行数据。

若要写入到表数据,请使用 Push-OutputBinding cmdlet,将 -Name TableBinding 参数和 -Value 参数设置为等于行数据。 有关更多详细信息,请参阅 PowerShell 示例

有两个选项可用于从函数输出表存储行消息:

选项 说明
返回值 将 function.json 中的 name 属性 设置为 。 使用此配置时,函数的返回值将作为表存储行保留。
命令性 将值传递给声明为 Out 类型的参数的 set 方法。 传递给 set 的值将保留为表行。

有关特定使用情况的详细信息,请参阅示例

异常和返回代码

绑定 参考
表错误代码
Blob、表、队列 存储错误代码
Blob、表、队列 故障排除

后续步骤