Enlaces de entrada de Azure Tables para Azure Functions

Use el enlace de entrada de Azure Tables para leer una tabla de Azure Cosmos DB for Table o Azure Table Storage.

Para obtener información sobre los detalles de instalación y configuración, vea la información general.

Importante

En este artículo se usan pestañas para admitir varias versiones del modelo de programación de Node.js. El modelo v4 está disponible de forma general y está diseñado para que los desarrolladores de JavaScript y TypeScript tengan una experiencia más flexible e intuitiva. Para más detalles acerca de cómo funciona el modelo v4, consulte la Guía para desarrolladores de Node.js de Azure Functions. Para obtener más información acerca de las diferencias entre v3 y v4, consulte la Guía de migración.

Ejemplo

La utilización del enlace depende de la versión del paquete de extensión y la modalidad de C# que se usa en la aplicación de funciones, que puede ser una de las siguientes:

Una función de C# compilada de la biblioteca de clases de procesos de trabajo aislados se ejecuta en un proceso aislado del entorno de ejecución.

Elija una versión para ver ejemplos del modo y la versión.

La clase MyTableData siguiente representa una fila de datos en la tabla:

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

La siguiente función, que se inicia mediante un desencadenador de Queue Storage, lee una clave de fila de la cola, que se usa para obtener la fila de la tabla de entrada. La expresión {queueTrigger} enlaza la clave de la fila a los metadatos del mensaje, que constituyen la cadena de mensaje.

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

La siguiente función desencadenada mediante Queue devuelve las cinco primeras entidades como objeto IEnumerable<T>, con el valor de clave de partición establecido como el mensaje en cola.

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

Las propiedades Filter y Take se usan para limitar el número de entidades devueltas.

En el ejemplo siguiente se muestra una función desencadenada por HTTP que devuelve una lista de objetos Person que se encuentran en una partición especificada del almacenamiento Table. En el ejemplo, la clave de partición se extrae de la ruta http y los elementos tableName y connection proceden de la configuración de la función.

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

La anotación TableInput también puede extraer los enlaces del cuerpo JSON de la solicitud, como se muestra en el ejemplo siguiente.

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

En el ejemplo siguiente se usa un filtro para buscar personas con un nombre concreto en una tabla de Azure y se limita el número de posibles coincidencias 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;
}

El siguiente ejemplo muestra un enlace de entrada de tabla que utiliza un desencadenador de cola para leer una sola fila de tabla. El enlace especifica un partitionKey y un rowKey. El valor rowKey "{queueTrigger}" de clave de fila indica que la clave de fila procede de la cadena del mensaje en la cola.

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

En el ejemplo siguiente se usa un desencadenador de cola para leer una fila de tabla única como entrada para una función.

En este ejemplo, la configuración de enlace especifica un valor explícito para la partitionKey de la tabla y utiliza una expresión para pasar a la rowKey. La expresión de rowKey, {queueTrigger}, indica que la clave de fila procede de la cadena del mensaje en la cola.

Configuración de enlace en 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 de PowerShell en run.ps1:

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

La siguiente función usa un desencadenador de HTTP para leer una fila de tabla única como entrada para una función.

En este ejemplo, la configuración de enlace especifica un valor explícito para el elemento partitionKey de la tabla y se usa una expresión para pasar al elemento rowKey. En la expresión rowKey, {id} indica que la clave de fila procede de la parte {id} de la ruta en la solicitud.

Configuración de enlace del archivo 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 de Python en el archivo __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}")

Con este enlace simple, no se puede controlar mediante programación un caso en el que no se encuentra ninguna fila que tenga un identificador de clave de fila. Para una selección de datos más detallada, use el SDK de almacenamiento.


Atributos

Las bibliotecas de C# en proceso y de proceso de trabajo aislado usan atributos para definir la función. En su lugar, el script de C# usa un archivo de configuración function.json como se describe en la Guía de scripting de C#.

En las bibliotecas de clases de C#, la clase TableInputAttribute admite las siguientes propiedades:

Propiedad de atributo Descripción
TableName Nombre de la tabla.
PartitionKey Opcional. Clave de partición de la entidad de tabla que se va a leer.
RowKey Opcional. Clave de fila de la entidad de tabla que se va a leer.
Take Opcional. Número máximo de entidades que se van a leer en un objeto IEnumerable<T>. No se puede usar con RowKey.
Filter Opcional. Expresión de filtro de OData para que las entidades lean en un objeto IEnumerable<T>. No se puede usar con RowKey.
Connection Nombre de una configuración de aplicación o colección de parámetros que especifica cómo conectarse al servicio de tablas. Consulte Conexiones.

anotaciones

En la biblioteca en tiempo de ejecución de funciones de Java, utilice la anotación @TableInput en los parámetros cuyo valor provendría del almacenamiento de la tabla. Esta anotación se puede usar con tipos nativos de Java, POJO o valores que aceptan valores NULL mediante Optional<T>. Esta anotación admite los siguientes elementos:

Elemento Descripción
name Nombre de la variable que representa la tabla o la entidad en el código de la función.
tableName Nombre de la tabla.
partitionKey Opcional. Clave de partición de la entidad de tabla que se va a leer.
rowKey Opcional. Clave de fila de la entidad de tabla que se va a leer.
take Opcional. Número máximo de entidades que se leerán.
filtro Opcional. Expresión de filtro de OData para la entrada de la tabla.
conexión Nombre de una configuración de aplicación o colección de parámetros que especifica cómo conectarse al servicio de tablas. Consulte Conexiones.

Configuración

En la tabla siguiente se explican las propiedades que puede establecer en el objeto options que se pasa al métodoinput.table().

Propiedad Descripción
tableName Nombre de la tabla.
partitionKey Opcional. Clave de partición de la entidad de tabla que se va a leer.
rowKey Opcional. Clave de fila de la entidad de tabla que se va a leer. No se puede usar con las propiedades take ni filter.
take Opcional. Número máximo de entidades que se devolverán. No se puede usar con rowKey.
filter Opcional. Expresión de filtro de OData para las entidades que se devolverá de la tabla. No se puede usar con rowKey.
connection Nombre de una configuración de aplicación o colección de parámetros que especifica cómo conectarse al servicio de tablas. Consulte Conexiones.

Configuración

En la siguiente tabla se explican las propiedades de configuración de enlace que se establecen en el archivo function.json.

Propiedad de function.json Descripción
type Se debe establecer en table. Esta propiedad se establece automáticamente cuando se crea el enlace en Azure Portal.
direction Se debe establecer en in. Esta propiedad se establece automáticamente cuando se crea el enlace en Azure Portal.
name Nombre de la variable que representa la tabla o la entidad en el código de la función.
tableName Nombre de la tabla.
partitionKey Opcional. Clave de partición de la entidad de tabla que se va a leer.
rowKey Opcional. Clave de fila de la entidad de tabla que se va a leer. No se puede usar con las propiedades take ni filter.
take Opcional. Número máximo de entidades que se devolverán. No se puede usar con rowKey.
filter Opcional. Expresión de filtro de OData para las entidades que se devolverá de la tabla. No se puede usar con rowKey.
connection Nombre de una configuración de aplicación o colección de parámetros que especifica cómo conectarse al servicio de tablas. Consulte Conexiones.

Cuando esté desarrollando localmente, agregue la configuración de la aplicación en el archivo local.settings.json de la colección Values.

Conexiones

La propiedad connection es una referencia a la configuración del entorno que especifica cómo se debe conectar la aplicación al servicio de tablas. Puede especificar lo siguiente:

Si el valor configurado es tanto una coincidencia exacta de una única configuración como una coincidencia de prefijo de otras configuraciones, se usa la coincidencia exacta.

Cadena de conexión

Para obtener una cadena de conexión para tablas en Azure Table Storage, siga los pasos que se muestran en Administración de las claves de acceso de la cuenta de almacenamiento. Para obtener una cadena de conexión para las tablas de Azure Cosmos DB for Table, siga los pasos que se muestran en Preguntas frecuentes sobre Azure Cosmos DB for Table.

La cadena de conexión debe almacenarse en una configuración de la aplicación con un nombre que coincida con el valor especificado por la propiedad connection de la configuración de enlace.

Si el nombre de la configuración de aplicación comienza con "AzureWebJobs", puede especificar solo el resto del nombre aquí. Por ejemplo, si establece connection en "MyStorage", el entorno en tiempo de ejecución de Functions busca una configuración de aplicación denominada "AzureWebJobsMyStorage". Si deja connection vacía, el entorno en tiempo de ejecución de Functions usa la cadena de conexión de almacenamiento predeterminada en la configuración de aplicación que se denomina AzureWebJobsStorage.

Conexiones basadas en identidades

Si usa la extensión Table API, en lugar de usar una cadena de conexión con un secreto, puede hacer que la aplicación use una identidad de Microsoft Entra. Esto solo se aplica al acceder a tablas en Azure Storage. Para usar una identidad, se define la configuración con un prefijo común que se asigna a la propiedad de connection en la configuración de desencadenador y enlace.

Si va a establecer connection en "AzureWebJobsStorage", consulte Conexión al almacenamiento de host con una identidad. Para todas las demás conexiones, la extensión requiere las siguientes propiedades:

Propiedad Plantilla de variable de entorno Descripción Valor de ejemplo
URI del servicio de tablas <CONNECTION_NAME_PREFIX>__tableServiceUri1 URI del plano de datos del servicio de tablas de Azure Storage al que se conecta, mediante el esquema HTTPS. https://<nombre_cuenta_almacenamiento>.table.core.windows.net

1<CONNECTION_NAME_PREFIX>__serviceUri se puede usar como alias. Si se proporcionan ambos formularios, se usa el formulario tableServiceUri. El formulario serviceUri no se puede usar cuando la configuración de conexión general se va a usar en blobs, colas o tablas.

Se pueden establecer otras propiedades para personalizar la conexión. Consulte Propiedades comunes para conexiones basadas en identidades.

El formulario serviceUri no se puede usar cuando la configuración de conexión general se va a usar en blobs, colas o tablas en Azure Storage. El URI solo puede designar el servicio de tablas. Como alternativa, puede proporcionar un URI específicamente para cada servicio del mismo prefijo, lo cual permite usar una sola conexión.

Cuando se hospeda en el servicio de Azure Functions, las conexiones basadas en identidades usan una identidad administrada. La identidad asignada por el sistema se usa de manera predeterminada, aunque se puede especificar una identidad asignada por el usuario con las propiedades credential y clientID. Tenga en cuenta que no se admite la configuración de una identidad asignada por el usuario con un identificador de recurso. Cuando se ejecuta en otros contextos, como el de desarrollo local, se usa en su lugar la identidad del desarrollador, aunque se puede personalizar. Consulte Desarrollo local con conexiones basadas en identidades.

Concesión de permiso a la identidad

Cualquier identidad que se utilice debe tener permisos para realizar las acciones previstas. Para la mayoría de los servicios de Azure, esto significa que debe asignar un rol en Azure RBAC mediante roles integrados o personalizados que proporcionen esos permisos.

Importante

Es posible que el servicio de destino muestre algunos permisos que no son necesarios para todos los contextos. Siempre que sea posible, respete el principio de privilegios mínimos y conceda solo los privilegios necesarios a la identidad. Por ejemplo, si la aplicación solo necesita poder leer desde un origen de datos, use un rol que solo tenga permiso de lectura. Sería inadecuado asignar un rol que también permita escribir en ese servicio, ya que sería un permiso excesivo para una operación de lectura. De forma similar, le interesa asegurarse de que la asignación de roles esté limitada solo a los recursos que se deben leer.

Debe crear una asignación de roles que proporcione acceso al servicio de tablas de Azure Storage en tiempo de ejecución. Los roles de administración, como Propietario, no son suficientes. En la tabla siguiente se muestran los roles integrados que se recomiendan cuando se usa la extensión para Azure Tables en Azure Storage durante el funcionamiento normal. Puede que la aplicación precise permisos adicionales en función del código que escriba.

Tipo de enlace Roles integrados de ejemplo (Azure Storage1)
Enlace de entrada Lector de datos de tabla de Storage
Enlace de salida Colaborador de datos de tabla de Storage

1 Si la aplicación se conecta a tablas de Azure Cosmos DB for Table, no se admite el uso de una identidad y la conexión debe usar una cadena de conexión.

Uso

La utilización del enlace depende de la versión del paquete de extensión y la modalidad de C# que se usa en la aplicación de funciones, que puede ser una de las siguientes:

Una función de C# compilada de la biblioteca de clases de procesos de trabajo aislados se ejecuta en un proceso aislado del entorno de ejecución.

Elija una versión para ver los detalles de utilización del modo y la versión.

Al trabajar con una sola entidad de tabla, el enlace de entrada de Azure Tables puede enlazarse a los siguientes tipos:

Tipo Descripción
Un tipo serializable JSON que implementa ITableEntity Functions intenta deserializar la entidad en un tipo de objeto CRL estándar (POCO). El tipo debe implementar ITableEntity o tener una propiedad de cadena RowKey y una propiedad de cadena PartitionKey.
TableEntity1 La entidad como tipo de diccionario.

Al trabajar con varias entidades desde una consulta, el enlace de entrada de Azure Tables puede enlazarse a los siguientes tipos:

Tipo Descripción
IEnumerable<T> donde T implementa ITableEntity Una enumeración de entidades devueltas por la consulta. Cada entrada representa una entidad. El tipo T debe implementar ITableEntity o tener una propiedad de cadena RowKey y una propiedad de cadena PartitionKey.
TableClient1 Un cliente conectado a la tabla. Ofrece el mayor control para procesar la tabla y puede utilizarse para escribir en ella si la conexión tiene permisos suficientes.

1 Para usar estos tipos, es necesario hacer referencia a Microsoft.Azure.Functions.Worker.Extensions.Tables 1.2.0 o posterior y a las dependencias comunes para los enlaces de tipo de SDK.

El atributo TableInput da acceso a la fila de tabla que desencadenó la función.

Obtenga los datos de fila de entrada mediante context.extraInputs.get().

Los datos se pasan al parámetro de entrada según especifica la clave name en el archivo function.json. La especificación de partitionKey y rowKey permite filtrar registros específicos.

Los datos de la tabla se pasan a la función como una cadena JSON. Anule la serialización del mensaje mediante una llamada a json.loads como se muestra en el ejemplo de entrada.

Para obtener detalles de utilización específicos, consulte Ejemplo.

Pasos siguientes