Compartilhar via


Associações de saída das Tabelas do Azure para o Azure Functions

Use uma associação de saída das Tabelas do Azure para gravar entidades em uma tabela no Azure Cosmos DB for Table ou no Armazenamento de Tabelas do Azure.

Para obter informações sobre a instalação e detalhes de configuração, confira a visão geral

Observação

Essa associação de saída dá suporte apenas à criação de novas entidades em uma tabela. Se for necessário atualizar uma entidade existente do código de função, use um SDK das Tabelas do Azure diretamente.

Importante

Este artigo usa guias para dar suporte a várias versões do modelo de programação Node.js. O modelo v4 normalmente está disponível e foi projetado para oferecer uma experiência mais flexível e intuitiva para desenvolvedores de JavaScript e TypeScript. Para obter mais detalhes sobre como funciona o modelo v4, consulte o Guia do desenvolvedor do Node.js para o Azure Functions. Para saber mais sobre as diferenças entre os modelos v3 e a v4, consulte o Guia de migração.

Exemplo

A função C# pode ser criada por meio de um dos seguintes modos C#:

  • Modelo de trabalho isolado: função C# compilada executada em um processo de trabalho que está isolado do runtime. É necessário um processo de trabalho isolado para dar suporte às funções C# executadas nas versões LTS e não LTS do .NET e do .NET Framework. As extensões para funções do processo de trabalho isoladas usam namespaces Microsoft.Azure.Functions.Worker.Extensions.*.
  • Modelo em processo: função C# compilada no mesmo processo que o runtime do Functions. Em uma variação desse modelo, o Functions pode ser executado usando scripts C#, que é compatível principalmente com a edição do portal C#. As extensões para funções dentro do processo usam namespaces Microsoft.Azure.WebJobs.Extensions.*.

A classe MyTableData a seguir representa uma linha de dados na tabela:

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

A função a seguir, que é iniciada por um gatilho de Armazenamento de Filas, grava uma nova entidade MyDataTable em uma tabela chamada MyDataTable.

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

O exemplo a seguir mostra uma função Java que usa um gatilho HTTP para gravar uma única linha de tabela.

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

O exemplo a seguir mostra uma função Java que usa um gatilho HTTP para gravar múltiplas linhas de tabela.

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

O exemplo a seguir mostra uma associação de saída de tabela que grava várias entidades de tabela.

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

O exemplo a seguir demonstra como gravar várias entidades em uma tabela a partir de uma função.

Configuração de associação no function.json:

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

Código do PowerShell no run.ps1:

param($InputData, $TriggerMetadata)

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

O exemplo a seguir demonstra como usar a associação de saída de armazenamento de Tabela. Configure a associação table no table atribuindo valores a name, tableName, partitionKey e connection:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "message",
      "type": "table",
      "tableName": "messages",
      "partitionKey": "message",
      "connection": "AzureWebJobsStorage",
      "direction": "out"
    },
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

A função a seguir gera um UUI exclusivo para o rowKey valor e persiste a mensagem no armazenamento de Tabelas.

import logging
import uuid
import json

import azure.functions as func

def main(req: func.HttpRequest, message: func.Out[str]) -> func.HttpResponse:

    rowKey = str(uuid.uuid4())

    data = {
        "Name": "Output binding message",
        "PartitionKey": "message",
        "RowKey": rowKey
    }

    message.set(json.dumps(data))

    return func.HttpResponse(f"Message created with the rowKey: {rowKey}")

Atributos

As bibliotecas C# em processo e de processo de trabalho isolado usam atributos para definir a função. Em vez disso, o script C# usa um arquivo de configuração function.json, conforme descrito no guia do script C#.

Em bibliotecas de classes C#, o TableInputAttribute dá suporte às seguintes propriedades:

Propriedade de atributo Descrição
TableName O nome da tabela na qual gravar.
PartitionKey Chave de partição da entidade de tabela para gravar.
RowKey A chave de linha da entidade de tabela para gravar.
Conexão O nome de uma configuração de aplicativo ou coleção de configurações que especifica como se conectar ao serviço de tabela. Confira a opção Conexões.

Anotações

Na biblioteca de tempo de execução de funções Java, use a anotação TableOutput em parâmetros para gravar valores nas tabelas. O atributo oferece suporte aos seguintes elementos:

Elemento Descrição
name O nome da variável usada no código da função que representa a tabela ou entidade.
dataType Define como o tempo de execução do Functions deve tratar o valor do parâmetro. Para saber mais, consulte DataType.
tableName O nome da tabela na qual gravar.
partitionKey Chave de partição da entidade de tabela para gravar.
rowKey A chave de linha da entidade de tabela para gravar.
connection O nome de uma configuração de aplicativo ou coleção de configurações que especifica como se conectar ao serviço de tabela. Confira a opção Conexões.

Configuração

A tabela a seguir explica as propriedades que você pode definir no objeto options transmitido para o método output.table().

Propriedade Descrição
tableName O nome da tabela na qual gravar.
partitionKey Chave de partição da entidade de tabela para gravar.
rowKey A chave de linha da entidade de tabela para gravar.
connection O nome de uma configuração de aplicativo ou coleção de configurações que especifica como se conectar ao serviço de tabela. Confira a opção Conexões.

Configuração

A tabela a seguir explica as propriedades de configuração de associação que você define no arquivo function.json.

Propriedade function.json Descrição
tipo Deve ser definido como table. Esse parâmetro é definido automaticamente quando você cria a associação no portal do Azure.
direction Deve ser definido como out. Esse parâmetro é definido automaticamente quando você cria a associação no portal do Azure.
name O nome da variável usada no código da função que representa a tabela ou entidade. Definido como $return para referenciar o valor de retorno da função.
tableName O nome da tabela na qual gravar.
partitionKey Chave de partição da entidade de tabela para gravar.
rowKey A chave de linha da entidade de tabela para gravar.
connection O nome de uma configuração de aplicativo ou coleção de configurações que especifica como se conectar ao serviço de tabela. Confira a opção Conexões.

Quando você estiver desenvolvendo localmente, adicione as configurações do aplicativo no arquivo local.settings.json na coleção Values.

conexões

A propriedade connection é uma referência à configuração de ambiente que especifica como o aplicativo deve se conectar ao serviço da tabela. Ela pode especificar:

Se o valor configurado for uma combinação exata para uma única configuração e um correspondência de prefixo para outras configurações, a correspondente exata será usada.

Cadeia de conexão

Para obter uma cadeia de conexão para tabelas no Armazenamento de Tabelas do Azure, execute as etapas mostradas em Gerenciar as chaves de acesso à conta de armazenamento. Para obter uma cadeia de conexão para tabelas no Azure Cosmos DB for Table, siga as etapas mostradas nas Perguntas frequentes sobre o Azure Cosmos DB for Table.

Essa cadeia de conexão deve ser armazenada em uma configuração de aplicativo com um nome que corresponda ao valor especificado pela propriedade connection da configuração de associação.

Se o nome de configuração do aplicativo começar com "AzureWebJobs", você pode especificar apenas o resto do nome aqui. Por exemplo, se você configurar connection para "MyStorage", o runtime do Functions procurará uma configuração de aplicativo chamada "AzureWebJobsMyStorage". Se você deixar connection vazio, o runtime de Functions usa a cadeia de caracteres de conexão de Armazenamento padrão na configuração de aplicativo chamada AzureWebJobsStorage.

Conexões baseadas em identidade

Se estiver usando a extensão de API de Tabelas, em vez de usar uma cadeia de conexão com um segredo, você pode fazer com que o aplicativo use uma identidade do Microsoft Entra. Isso só se aplica ao acessar as tabelas no Armazenamento do Microsoft Azure. Para usar uma identidade, você define as configurações sob um prefixo comum que mapeia para a propriedade connection na configuração do gatilho e da vinculação.

Se estiver definindo connection como "AzureWebJobsStorage", confira Como se conectar ao armazenamento host com uma identidade. Para todas as outras conexões, a extensão requer as seguintes propriedades:

Propriedade Modelo de variável de ambiente Descrição Valor de exemplo
URI do serviço de tabela <CONNECTION_NAME_PREFIX>__tableServiceUri1 O URI do plano de dados do serviço de tabela do Armazenamento do Microsoft Azure ao qual você está se conectando usando o esquema HTTPS. https://<storage_account_name>.table.core.windows.net

1 <CONNECTION_NAME_PREFIX>__serviceUri pode ser usado como um alias. Se as duas formas forem fornecidas, a forma usada será tableServiceUri. O formulário serviceUri não pode ser usado quando a configuração geral da conexão deve ser usada em blobs, filas e/ou tabelas.

Outras propriedades podem ser definidas para personalizar a conexão. Confira Propriedades comuns para conexões baseadas em identidade.

A forma serviceUri não pode ser usada quando a configuração geral da conexão se destina a ser usada em blobs, filas de espera e/ou tabelas no Armazenamento do Microsoft Azure. O URI só pode designar o serviço da tabela. Como alternativa, você pode fornecer um URI especificamente para cada serviço no mesmo prefixo, permitindo o uso de uma única conexão.

Quando hospedadas no serviço de Azure Functions, as conexões baseadas em identidade usam uma identidade gerenciada. A identidade atribuída pelo sistema é usada por padrão, embora a identidade atribuída pelo usuário possa ser especificada com as propriedades credential e clientID. Observe que não há suporte para configurar uma identidade atribuída pelo usuário com uma ID de recurso. Quando executado em outros contextos, como desenvolvimento local, a identidade do desenvolvedor é usada, embora isso possa ser personalizado. Confira Desenvolvimento local com conexões baseadas em identidade.

Conceder permissão para a identidade

Qualquer identidade que esteja sendo usada deve ter permissões para executar as ações pretendidas. Para a maioria dos serviços do Azure, isso significa que será necessário atribuir uma função no Azure RBAC, usando as funções internas ou as personalizadas que fornecem essas permissões.

Importante

Algumas permissões que não são necessárias em todos os contextos podem ser expostas pelo serviço de destino. Sempre que possível, siga o princípio do privilégio mínimo, concedendo à identidade apenas os privilégios necessários. Por exemplo, se o aplicativo precisar apenas ser capaz de ler uma fonte de dados, use uma função que só tenha permissão de leitura. Seria inapropriado atribuir uma função que também permitisse a gravação nesse serviço, pois seria um excesso de permissões para uma operação de leitura. Da mesma forma, seria melhor garantir que a atribuição da função tivesse o escopo apenas sobre os recursos que precisam ser lidos.

Você precisará criar uma atribuição de função que forneça acesso ao serviço de tabela do Armazenamento do Azure em runtime. As funções de gerenciamento como a de Proprietário não são suficientes. A tabela a seguir mostra as funções internas recomendadas ao usar a extensão de Tabelas do Azure no Armazenamento do Azure em operação normal. Seu aplicativo pode exigir permissões adicionais com base no código escrito por você.

Tipo de associação Exemplo de funções internas (Armazenamento do Microsoft Azure1)
Associação de entrada Leitor de dados de tabela de armazenamento
Associação de saída Colaborador de dados da tabela de armazenamento

1 Se o aplicativo estiver se conectando a tabelas no Azure Cosmos DB for Table, não haverá suporte para o uso de uma identidade e a conexão deverá usar uma cadeia de conexão.

Uso

O uso da associação depende da versão do pacote de extensão e da modalidade C# usada no aplicativo de funções, que pode ser:

Uma função C# compilada da biblioteca de classes do processo de trabalho isolado é executada em um processo isolado do runtime.

Escolha uma versão para ver os detalhes de uso do modo e da versão.

Quando você deseja que a função seja gravada em uma única entidade, a associação de saída de tabelas do Azure pode ser associada aos seguintes tipos:

Type Descrição
Um tipo de JSON serializável que implementa [ITableEntity] O Functions tenta serializar um tipo de objeto CRL básico antigo (POCO) como a entidade. O tipo deve implementar uma [ITableEntity] ou ter uma propriedade RowKey de cadeia de caracteres e uma propriedade PartitionKey de cadeia de caracteres.

Quando você quiser que a função seja gravada em várias entidades, a associação de saída das Tabelas do Azure poderá ser associada aos seguintes tipos:

Type Descrição
T[] onde T é um dos tipos de entidade única Uma matriz contendo várias entidades. Cada entrada representa uma entidade.

Para outros cenários de saída, crie e use tipos diretamente do Azure.Data.Tables.

Há duas opções para gerar uma linha de armazenamento de Tabela de uma função usando a anotação TableStorageOutput:

Opções Descrição
Valor de retorno Ao aplicar a anotação à própria função, o valor retornado da função se mantém como uma linha de armazenamento de Tabela.
Obrigatório Para definir a linha da tabela de modo explícito, aplique a anotação a um parâmetro específico do tipo OutputBinding<T>, em que T inclua as propriedades PartitionKey e RowKey. É possível acompanhar essas propriedades implementando ITableEntity ou herdando TableEntity.

Defina os dados da linha de saída retornando o valor ou usando context.extraOutputs.set().

Para gravar em dados de tabela, use o cmdlet Push-OutputBinding e defina os parâmetros -Name TableBinding e -Value de forma igual aos dados da linha. Confira o exemplo do PowerShell para mais detalhes.

Existem duas opções para gerar uma mensagem de linha de armazenamento de Tabela a partir de uma função:

Opções Descrição
Valor de retorno defina a propriedade name no name como $return. Com essa configuração, o valor retornado da função se mantém como uma linha de armazenamento de Tabela.
Obrigatório passe um valor para definir o método do parâmetro declarado como um tipo de Saída. O valor passado para set será mantido como uma linha da tabela.

Para obter detalhes de uso específicos, consulte Exemplo.

Exceções e códigos de retorno

Associação Referência
Tabela Códigos de erro de tabelas
Blob, tabela, fila Códigos de erro de armazenamento
Blob, tabela, fila Solução de problemas

Próximas etapas