Associações de entrada das Tabelas do Azure para o Azure Functions

Use a associação de entrada das Tabelas do Azure para ler 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.

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

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 exemplos de uso do modo e da versão.

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 Fila, lê uma chave de linha da fila, que é usada para obter a linha da tabela de entrada. A expressão {queueTrigger} associa a chave de linha aos metadados da mensagem, que é a cadeia de caracteres da mensagem.

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

A função disparada por fila a seguir retorna as cinco primeiras entidades como um IEnumerable<T>, com o valor da chave de partição definido como a mensagem da fila.

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

As propriedades Filter e Take são usadas para limitar o número de entidades retornadas.

O exemplo a seguir mostra uma função disparada por HTTP que retorna uma lista dos objetos pessoais que estão em uma partição especificada no Armazenamento de Tabelas. No exemplo, a chave de partição é extraída da rota http e o tableName e a conexão são das configurações de função.

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

A anotação TableInput também pode extrair as associações do corpo json da solicitação, conforme mostra o exemplo a seguir.

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

O exemplo a seguir usa um filtro para consultar pessoas com um nome específico em uma Tabela do Azure e limita o número de possíveis correspondências a 10 resultados.

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

O exemplo a seguir mostra uma associação de entrada de tabela que usa um gatilho de fila para ler uma única linha de tabela. A associação especifica um partitionKey e um rowKey. O rowKey valor “{queueTrigger}” indica que a chave de linha foi obtida da cadeia de caracteres da mensagem da fila.

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

A função a seguir usa um gatilho de fila para ler uma linha da tabela como uma entrada para uma função.

Neste exemplo, a configuração de associação especifica um valor explícito para partitionKey da tabela e usa uma expressão para passar para o rowKey. A expressão rowKey, {queueTrigger}, indica que a chave de linha vem da cadeia de caracteres da mensagem da fila.

Configuração de associação no 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
}

Código do PowerShell no run.ps1:

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

A função a seguir usa um gatilho de HTTP para ler uma linha da tabela como uma entrada para uma função.

Neste exemplo, a configuração de associação especifica um valor explícito para partitionKey da tabela e usa uma expressão para passar para o rowKey. A expressão rowKey, {id} indica que a chave de linha vem da parte {id} da rota na solicitação.

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

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

Código Python no arquivo __init__.py:

import json

import azure.functions as func

def main(req: func.HttpRequest, messageJSON) -> func.HttpResponse:

    message = json.loads(messageJSON)
    return func.HttpResponse(f"Table row: {messageJSON}")

Com essa associação simples, você não pode manipular programaticamente um caso em que nenhuma linha que tenha uma ID de chave de linha seja encontrada. Para uma seleção de dados mais refinada, use o SDK de armazenamento.


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.
PartitionKey Opcional. Chave de partição da entidade de tabela para leitura.
RowKey Opcional. Chave de linha da entidade de tabela para leitura.
Take Opcional. O número máximo de entidades para ler em um IEnumerable<T>. Não pode ser usado com RowKey.
Filter Opcional. Uma expressão de filtro OData para entidades lerem em um IEnumerable<T>. Não pode ser usado com RowKey.
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 runtime de funções Java, use a anotação @TableInput nos parâmetros cujo valor possa ser proveniente do Armazenamento de Tabelas. Essa anotação pode ser usada com tipos nativos do Java, POJOs ou valores que permitem valor nulos usando Optional<T>. Essa anotação dá suporte aos seguintes elementos:

Elemento Descrição
name O nome da variável que representa a tabela ou entidade no código de função.
tableName O nome da tabela.
partitionKey Opcional. Chave de partição da entidade de tabela para leitura.
rowKey Opcional. Chave de linha da entidade de tabela para leitura.
take Opcional. O número máximo de entidades a ler.
filter Opcional. Uma expressão de filtro OData para a entrada de tabela.
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 input.table().

Propriedade Descrição
tableName O nome da tabela.
partitionKey Opcional. Chave de partição da entidade de tabela para leitura.
rowKey Opcional. Chave de linha da entidade de tabela para leitura. Não pode ser usado com take ou filter.
take Opcional. O número máximo de entidades a retornar. Não pode ser usado com rowKey.
filter Opcional. Uma expressão de filtro OData para as entidades retornarem da tabela. Não pode ser usado com rowKey.
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 in. Esse parâmetro é definido automaticamente quando você cria a associação no portal do Azure.
name O nome da variável que representa a tabela ou entidade no código de função.
tableName O nome da tabela.
partitionKey Opcional. Chave de partição da entidade de tabela para leitura.
rowKey Opcional. Chave de linha da entidade de tabela para leitura. Não pode ser usado com take ou filter.
take Opcional. O número máximo de entidades a retornar. Não pode ser usado com rowKey.
filter Opcional. Uma expressão de filtro OData para as entidades retornarem da tabela. Não pode ser usado com rowKey.
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 de 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.

Ao trabalhar com uma única entidade de tabela, a associação de entrada das Tabelas do Azure pode ser associada aos seguintes tipos:

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

Ao trabalhar com várias entidades de uma consulta, a associação de entrada das Tabelas do Azure pode ser associada aos seguintes tipos:

Type Descrição
IEnumerable<T> onde T implementa ITableEntity Uma enumeração de entidades retornada pela consulta. Cada entrada representa uma entidade. O tipo T deve implementar uma [ITableEntity] ou ter uma propriedade RowKey de cadeia de caracteres e uma propriedade PartitionKey de cadeia de caracteres.
TableClient1 Um cliente conectado à tabela. Isso oferece a maior parte do controle para processar a tabela e pode ser usado para gravar nela se a conexão tiver permissão suficiente.

1 Para usar esses tipos, você precisará mencionar o Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 1.2.0 ou posterior e as dependências comuns para associações do tipo SDK.

O atributo TableInput concede a você acesso à linha da tabela que disparou a função.

Obtenha os dados da linha de entrada usando context.extraInputs.get().

Os dados são passados para o parâmetro de entrada, conforme especificado pela chave name no arquivo name. Especificar o partitionKey e rowKey permite a você filtrar para registros específicos.

Os dados da tabela são passados para a função como uma cadeia de caracteres JSON. Desserialize a mensagem chamando json.loads conforme mostrado no json.loads de entrada.

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

Próximas etapas