Enlaces de salida de Azure Tables para Azure Functions

Use un enlace de salida de Azure Tables para escribir entidades en 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, consulte la información general.

Nota:

Este enlace de salida solo admite la creación de nuevas entidades en una tabla. Si necesita actualizar una entidad existente desde el código de la función, use directamente un SDK de Azure Tables.

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

Se puede crear una función C# mediante uno de los siguientes modos de C#:

  • Modelo de trabajo aislado: función compilada en C# que se ejecuta en un proceso trabajador aislado del tiempo de ejecución. Se requiere un proceso de trabajo aislado para admitir funciones de C# ejecutándose en versiones de .NET que son y no son LTS y .NET Framework. Las extensiones para las funciones de proceso de trabajo aisladas usan espacios de nombres Microsoft.Azure.Functions.Worker.Extensions.*.
  • Modelo en curso: función C# compilada que se ejecuta en el mismo proceso que el tiempo de ejecución de Functions. En una variación de este modelo, Functions se puede ejecutar mediante el scripting de C#, que se admite principalmente para la edición del portal de C#. Las extensiones para funciones en proceso utilizan espacios de nombres Microsoft.Azure.WebJobs.Extensions.*.

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 función siguiente, que se inicia mediante un desencadenador de Queue Storage, escribe una nueva entidad MyDataTable en una tabla denominada 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}"
    };
}

En el ejemplo siguiente se muestra una función de Java que usa un desencadenador HTTP para escribir una única fila de la tabla.

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

En el ejemplo siguiente se muestra una función de Java que usa un desencadenador HTTP para escribir una varias filas de tabla.

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

El siguiente ejemplo se muestra un enlace de salida de tabla que escribe varias entidades de tabla.

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

En el siguiente ejemplo se muestra cómo escribir varias entidades en una tabla a partir de una función.

Configuración de enlace en function.json:

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

Código de PowerShell en run.ps1:

param($InputData, $TriggerMetadata)

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

En el ejemplo de código siguiente se muestra cómo utilizar el enlace de la salida de Table Storage. Configure el enlace de table en function.json mediante la asignación de valores a name, tableName, partitionKey y 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"
    }
  ]
}

La función siguiente genera un UUI único para el valor rowKey y guarda el mensaje en Table Storage.

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

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 en la que se va a escribir.
PartitionKey Clave de partición de la entidad de tabla que se va a escribir.
RowKey Clave de fila de la entidad de tabla que se va a escribir.
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 del entorno de ejecución de funciones de Java, utilice la anotación TableOutput en los parámetros para escribir valores en las tablas. El atributo admite los siguientes elementos:

Elemento Descripción
name Nombre de la variable que se usa en el código de la función que representa la tabla o entidad.
dataType Define cómo debe tratar Functions Runtime el valor del parámetro. Para obtener más información, consulte dataType.
tableName Nombre de la tabla en la que se va a escribir.
partitionKey Clave de partición de la entidad de tabla que se va a escribir.
rowKey Clave de fila de la entidad de tabla que se va a escribir.
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 tabla siguiente se explican las propiedades que puede establecer en el objeto options que se pasa al métodooutput.table().

Propiedad Descripción
tableName Nombre de la tabla en la que se va a escribir.
partitionKey Clave de partición de la entidad de tabla que se va a escribir.
rowKey Clave de fila de la entidad de tabla que se va a escribir.
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 out. Esta propiedad se establece automáticamente cuando se crea el enlace en Azure Portal.
name Nombre de la variable que se usa en el código de la función que representa la tabla o entidad. Se establece en $return para hacer referencia al valor devuelto de la función.
tableName Nombre de la tabla en la que se va a escribir.
partitionKey Clave de partición de la entidad de tabla que se va a escribir.
rowKey Clave de fila de la entidad de tabla que se va a escribir.
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.

Cuando quiera que la función escriba en una sola entidad, el enlace de salida de Azure Tables puede enlazarse a los siguientes tipos:

Tipo Descripción
Tipo serializable JSON que implementa [ITableEntity] Functions intenta serializar un tipo de objeto de SQL Server (POCO) como entidad. El tipo debe implementar [ITableEntity] o tener una propiedad de cadena RowKey y una propiedad de cadena PartitionKey.

Cuando quiera que la función escriba en múltiples entidades, el enlace de salida de Azure Tables puede enlazarse a los siguientes tipos:

Tipo Descripción
T[] donde T es uno de los tipos de entidad único Matriz que contiene varias entidades. Cada entrada representa una entidad.

Para otros escenarios de salida, cree y use tipos de Azure.Data.Tables directamente.

Hay dos opciones para la generación de una fila de Table Storage desde una función mediante la anotación TableStorageOutput:

Opciones Descripción
Valor devuelto Al aplicar la anotación a la propia función, el valor devuelto de la función se conserva como una fila de Table Storage.
Imperativo Para establecer explícitamente la fila de la tabla, aplique la anotación a un parámetro específico de tipo OutputBinding<T>, donde T incluye las propiedades PartitionKey y RowKey. Puede acompañar a estas propiedades mediante la implementación de ITableEntity o la herencia de TableEntity.

Acceda a los datos de la fila de salida devolviendo el valor o utilizando context.extraOutputs.set().

Para escribir en los datos de la tabla, use el cmdlet Push-OutputBinding, establezca el parámetros -Name TableBinding y el parámetro -Value igual que los datos de la fila. Consulte el ejemplo de PowerShell para más detalles.

Hay dos opciones para la generación de un mensaje de fila de Table Storage desde una función:

Opciones Descripción
Valor devuelto Establezca la propiedad name de function.json en $return. Con esta configuración, el valor devuelto de la función se conserva como una fila de Table Storage.
Imperativo Pase un valor al método set del parámetro declarado como tipo Out. El valor pasado a set se conserva como una fila de tabla.

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

Excepciones y códigos de retorno

Enlace Referencia
Tabla Códigos de error de tabla
Blob, tabla, cola Códigos de error de almacenamiento
Blob, tabla, cola Solución de problemas

Pasos siguientes