Liaisons d’entrée Tables Azure pour Azure Functions

Utilisez la liaison d’entrée des Tables Azure pour lire une table dans Azure Cosmos DB for Table ou le Stockage Table Azure.

Pour plus d’informations sur les détails d’installation et de configuration, consultez la vue d’ensemble.

Important

Cet article utilise des onglets pour prendre en charge plusieurs versions du modèle de programmation Node.js. Le modèle v4 est en disponibilité générale. Il est conçu pour offrir une expérience plus flexible et intuitive aux développeurs JavaScript et TypeScript. Pour plus d’informations sur le fonctionnement du modèle v4, reportez-vous au guide du développeur Azure Functions Node.js. En savoir plus sur les différences entre v3 et v4 dans le guide de migration.

Exemple

L’utilisation de la liaison dépend de la version du package d’extension et de la modalité C# utilisée dans votre application de fonction, qui peut être l’une des suivantes :

Une bibliothèque de classes de processus Worker isolé est une fonction C# compilée exécutée dans un processus Worker isolé du runtime.

Choisissez une version pour afficher des exemples pour le mode et la version.

La classe MyTableData suivante représente une ligne de données dans la table :

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

Démarrée par un déclencheur Stockage File d’attente, la fonction suivante lit une clé de ligne à partir de la file d’attente. Celle-ci est utilisée pour obtenir la ligne de la table d’entrée. L’expression {queueTrigger} lie la clé de ligne aux métadonnées de message, laquelle correspond à la chaîne de message.

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

Déclenchée par une file d’attente, la fonction suivante retourne les cinq premières entités en tant que IEnumerable<T>, avec la valeur de clé de partition définie en tant que message de file d’attente.

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

Les propriétés Filter et Take permettent de limiter le nombre d’entités retournées.

L’exemple suivant illustre une fonction déclenchée par HTTP qui retourne une liste d’objets Person qui se trouvent dans une partition spécifiée du stockage de table. Dans l’exemple, la clé de partition est extraite de l’itinéraire http, tandis que le nom de table (tableName) et la connexion proviennent des paramètres de fonction.

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

L’annotation TableInput peut également extraire les liaisons du corps JSON de la requête, comme le montre l’exemple suivant.

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

L’exemple suivant utilise le filtre pour rechercher des personnes portant un nom spécifique dans une table Azure, et limite le nombre de correspondances possibles à 10 résultats.

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

L’exemple suivant montre une liaison d’entrée de table qui utilise un déclencheur de file d’attente pour lire une seule ligne de tableau. La liaison spécifie une partitionKey et une rowKey. La valeur rowKey "{queueTrigger}" indique que la clé de ligne provient de la chaîne de message de file d’attente.

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

La fonction suivante utilise un déclencheur de file d'attente pour lire une seule ligne de table comme entrée d'une fonction.

Dans cet exemple, la configuration de liaison spécifie une valeur explicite pour la partitionKey de la table et utilise une expression à transmettre à la rowKey. L'expression rowKey, {queueTrigger}, indique que la clé de ligne provient de la chaîne de messages de la file d'attente.

Configuration de liaison dans 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
}

Code PowerShell dans run.ps1 :

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

La fonction suivante utilise un déclencheur HTTP pour lire une seule ligne de table comme entrée d’une fonction.

Dans cet exemple, la configuration de liaison spécifie une valeur explicite pour la partitionKey de la table et utilise une expression à transmettre à la rowKey. L’expression rowKey, {id}, indique que la clé de ligne provient de la partie {id} de l’itinéraire dans la requête.

Configuration de liaison dans le fichier 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
}

Code Python dans le fichier __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}")

Avec cette liaison simple, vous ne pouvez pas gérer par programmation un cas dans lequel aucune ligne avec un ID de clé de ligne n’a été trouvée. Pour une sélection de données plus fine, utilisez le SDK de stockage.


Attributs

Les bibliothèques C# in-process et de processus Worker isolé utilisent des attributs pour définir la fonction. Le script C# utilise à la place un fichier de configuration function.json comme décrit dans le guide de script C#.

Dans les bibliothèques de classes C#, TableInputAttribute prend en charge les propriétés suivantes :

Propriété d’attribut Description
TableName Nom de la table.
PartitionKey facultatif. Clé de partition de l’entité de table à lire.
RowKey facultatif. Clé de ligne de l’entité de table à lire.
Take facultatif. Nombre maximal d’entités à lire dans un IEnumerable<T>. Impossible à utiliser avec RowKey.
Filter facultatif. Expression de filtre OData pour les entités à lire dans un IEnumerable<T>. Impossible à utiliser avec RowKey.
Connection Nom d’un paramètre d’application ou d’une collection de paramètres d’application qui spécifie la façon de se connecter au service de table. Consultez Connexions.

Annotations

Dans la bibliothèque du runtime des fonctions Java, utilisez l’annotation @TableInput sur les paramètres dont la valeur proviendrait du Stockage Table. Vous pouvez utiliser cette annotation avec des types Java natifs, des objets POJO ou des valeurs Null à l’aide de Optional<T>. Cette annotation prend en charge les éléments suivants :

Élément Description
name Nom de la variable qui représente la table ou l’entité dans le code de la fonction.
tableName Nom de la table.
partitionKey facultatif. Clé de partition de l’entité de table à lire.
rowKey facultatif. Clé de ligne de l’entité de table à lire.
prendre facultatif. Nombre maximal d’entités à lire.
filtrer facultatif. Expression de filtre OData pour l’entrée de table.
connexion Nom d’un paramètre d’application ou d’une collection de paramètres d’application qui spécifie la façon de se connecter au service de table. Consultez Connexions.

Configuration

Le tableau suivant explique les propriétés que vous pouvez définir pour l’objet options passé à la méthode input.table().

Propriété Description
tableName Nom de la table.
partitionKey facultatif. Clé de partition de l’entité de table à lire.
rowKey facultatif. Clé de ligne de l’entité de table à lire. Ne peut pas être utilisé avec take ou filter.
take facultatif. Nombre maximal d’entités à retourner. Impossible à utiliser avec rowKey.
filter facultatif. Expression de filtre OData pour les entités à retourner à partir de la table. Impossible à utiliser avec rowKey.
connection Nom d’un paramètre d’application ou d’une collection de paramètres d’application qui spécifie la façon de se connecter au service de table. Consultez Connexions.

Configuration

Le tableau suivant décrit les propriétés de configuration de liaison que vous définissez dans le fichier function.json.

Propriété function.json Description
type Cette propriété doit être définie sur table. Cette propriété est définie automatiquement lorsque vous créez la liaison dans le portail Azure.
direction Cette propriété doit être définie sur in. Cette propriété est définie automatiquement lorsque vous créez la liaison dans le portail Azure.
name Nom de la variable qui représente la table ou l’entité dans le code de la fonction.
tableName Nom de la table.
partitionKey facultatif. Clé de partition de l’entité de table à lire.
rowKey facultatif. Clé de ligne de l’entité de table à lire. Ne peut pas être utilisé avec take ou filter.
take facultatif. Nombre maximal d’entités à retourner. Impossible à utiliser avec rowKey.
filter facultatif. Expression de filtre OData pour les entités à retourner à partir de la table. Impossible à utiliser avec rowKey.
connection Nom d’un paramètre d’application ou d’une collection de paramètres d’application qui spécifie la façon de se connecter au service de table. Consultez Connexions.

Lorsque vous développez en local, ajoutez vos paramètres d’application dans le fichier local.settings.json de la collection Values.

Connexions

La propriété connection est une référence à la configuration de l’environnement qui spécifie la façon dont l’application doit se connecter à votre service de table. Elle peut spécifier :

Si la valeur configurée est à la fois une correspondance exacte pour un paramètre unique et une correspondance de préfixe pour d’autres paramètres, la correspondance exacte est utilisée.

Chaîne de connexion

Pour obtenir une chaîne de connexion pour les tables dans le Stockage Azure Table, suivez les étapes indiquées dans Gérer les clés d’accès au compte de stockage. Pour obtenir une chaîne de connexion pour les tables dans Azure Cosmos DB pour Table, suivez les étapes indiquées dans la FAQ sur Azure Cosmos DB for Table.

Cette chaîne de connexion doit être stockée dans un paramètre d’application dont le nom correspond à la valeur spécifiée par la propriété connection de la configuration de liaison.

Si le nom du paramètre d’application commence par « AzureWebJobs », vous ne pouvez spécifier que le reste du nom ici. Par exemple, si vous définissez connection sur « MyStorage », le runtime Functions recherche un paramètre d’application nommé « AzureWebJobsMyStorage ». Si vous laissez connection vide, le runtime Functions utilise la chaîne de connexion de stockage par défaut dans le paramètre d’application nommé AzureWebJobsStorage.

Connexions basées sur l’identité

Si vous utilisez l’extension de l’API Tables, au lieu d’utiliser une chaîne de connexion avec un secret, vous pouvez définir l’application pour qu’elle utilise une identité Microsoft Entra. Cela s’applique uniquement lors de l’accès aux tables dans le Stockage Azure. Pour utiliser une identité, vous devez définir les paramètres sous un préfixe commun qui correspond à la propriété connection dans le déclencheur et la configuration de liaison.

Si vous définissez connection sur « AzureWebJobsStorage », consultez la section Connexion au stockage hôte avec une identité. Pour toutes les autres connexions, l’extension nécessite les propriétés suivantes :

Propriété Modèle de variable d’environnement Description Valeur d'exemple
URI du service de table <CONNECTION_NAME_PREFIX>__tableServiceUri1 URI du plan de données du service de table Stockage Azure auquel vous vous connectez, à l’aide du schéma HTTPS. https://<storage_account_name>.table.core.windows.net

1 <CONNECTION_NAME_PREFIX>__serviceUri peut être utilisé comme alias. Si les deux formes sont fournies, la forme tableServiceUri est utilisée. La forme serviceUri ne peut pas être utilisée lorsque la configuration globale de la connexion doit être utilisée sur des objets blob, des files d’attente et/ou des tables.

D’autres propriétés peuvent être définies pour personnaliser la connexion. Consultez Propriétés communes pour les connexions basées sur l’identité.

La forme serviceUri ne peut pas être utilisée lorsque la configuration globale de la connexion doit être utilisée sur des objets blob, des files d’attente et/ou des tables dans le Stockage Azure. L’URI ne peut désigner que le service de table. Vous pouvez également fournir un URI spécifique pour chaque service, sous le même préfixe en autorisant l’utilisation d’une connexion unique.

Quand elles sont hébergées dans le service Azure Functions, les connexions basées sur une identité utilisent une identité managée. L’identité attribuée par le système est utilisée par défaut, bien qu’une identité attribuée par l’utilisateur puisse être spécifiée avec les propriétés credential et clientID. Notez que la configuration d’une identité affectée par l’utilisateur avec un ID de ressource n’est pas prise en charge. Lors d’une exécution dans d’autres contextes, tels que le développement local, votre identité de développeur est utilisée à la place, même si cela peut être personnalisé. Consultez Développement local avec connexions basées sur une identité.

Accorder l’autorisation à l’identité

Quelle que soit l’identité utilisée, elle doit avoir les autorisations nécessaires pour effectuer les actions prévues. Pour la plupart des services Azure, cela signifie que vous devez attribuer un rôle dans Azure RBAC en utilisant des rôles intégrés ou personnalisés qui fournissent ces autorisations.

Important

Parmi les autorisations exposées par le service cible, certaines ne sont peut-être pas nécessaires pour tous les contextes. Dans la mesure du possible, adhérez au principe du privilège minimum, en accordant à l’identité uniquement les privilèges nécessaires. Par exemple, si l’application a juste besoin de pouvoir lire à partir d’une source de données, utilisez un rôle qui a uniquement l’autorisation de lecture. Il serait inapproprié d’attribuer un rôle qui autorise aussi l’écriture dans ce service, car ce serait une autorisation excessive pour une opération de lecture. De même, vous voudrez vous assurer que l’attribution de rôle est limitée aux seules ressources qui doivent être lues.

Vous devez créer une attribution de rôle qui donne accès à votre service de table Stockage Azure au moment de l’exécution. Les rôles de gestion comme Propriétaire ne sont pas suffisants. Le tableau suivant présente les rôles intégrés qui sont recommandés quand vous utilisez l’extension Tables Azure sur Stockage Azure dans le cadre d’un fonctionnement normal. Votre application peut nécessiter des autorisations supplémentaires en fonction du code que vous écrivez.

Type de liaison Exemples de rôles intégrés (Stockage Azure1)
Liaison d’entrée Lecteur de données de table du stockage
Liaison de sortie Contributeur aux données de table du stockage

1 Si votre application se connecte à des tables dans Azure Cosmos DB for Table, l’utilisation d’une identité n’est pas prise en charge et la connexion doit utiliser une chaîne de connexion.

Usage

L’utilisation de la liaison dépend de la version du package d’extension et de la modalité C# utilisée dans votre application de fonction, qui peut être l’une des suivantes :

Une bibliothèque de classes de processus Worker isolé est une fonction C# compilée exécutée dans un processus Worker isolé du runtime.

Choisissez une version pour afficher les détails d’utilisation du mode et de la version.

Lors de l’utilisation d’une seule entité de table, la liaison d’entrée Tables Azure peut être liée aux types suivants :

Type Description
Type sérialisable JSON qui implémente ITableEntity Functions tente de désérialiser l’entité dans un type d’objet POCO (Plain-Old CLR Object). Le type doit implémenter ITableEntity ou avoir des propriétés de chaîne RowKey et PartitionKey.
TableEntity1 Entité en tant que type de type dictionnaire.

Quand vous utilisez plusieurs entités à partir d’une requête, la liaison d’entrée Tables Azure peut être liée aux types suivants :

Type Description
IEnumerable<T>T implémente ITableEntity Énumération des entités renvoyées par la requête. Chaque entrée représente une entité. Le type T doit implémenter ITableEntity ou avoir des propriétés de chaîne RowKey et PartitionKey.
TableClient1 Client connecté à la table. Cela offre un meilleur contrôle pour le traitement de la table et peut être utilisé pour écrire dans celle-ci si la connexion dispose d’autorisations suffisantes.

1 Pour utiliser ces types, vous devez référencer Microsoft.Azure.Functions.Worker.Extensions.Tables 1.2.0 ou version ultérieure et les dépendances courantes pour les liaisons de type kit de développement logiciel (SDK).

L’attribut TableInput vous donne accès à la ligne de table qui ayant déclenché la fonction.

Obtenez les données de ligne d’entrée à l’aide de context.extraInputs.get().

Les données sont transmises au paramètre d'entrée comme spécifié par la clé name dans le fichier name. La spécification de partitionKey et rowKey vous permet de filtrer des enregistrements spécifiques.

Les données de table sont passées à la fonction sous la forme d’une chaîne JSON. Désérialisez le message en appelant json.loads comme dans l’json.loads d’entrée.

Pour des informations spécifiques sur l’utilisation, consultez Exemple.

Étapes suivantes