Azure Functions における Azure Functions の入力バインド

Azure テーブルの入力バインドを使用して、Azure Cosmos DB for Table または Azure Table Storage のテーブルを読み取ります。

セットアップと構成の詳細については、概要に関するページをご覧ください。

重要

この記事では、タブを使用して、Node.js プログラミング モデルの複数のバージョンに対応しています。 v4 モデルは一般提供されており、JavaScript と TypeScript の開発者にとって、より柔軟で直感的なエクスペリエンスが得られるように設計されています。 v4 モデルの動作の詳細については、Azure Functions Node.js 開発者ガイドを参照してください。 v3 と v4 の違いの詳細については、移行ガイドを参照してください。

バインドの使用方法は、拡張機能パッケージのバージョンと、関数アプリで使用される C# のモダリティによって異なり、次のいずれかになります。

分離ワーカー プロセス クラス ライブラリでコンパイルされた C# 関数は、ランタイムから分離されたプロセスで実行されます。

バージョンを選択すると、モードとバージョンの例が表示されます。

次の MyTableData のクラスは、テーブル内のデータの行を表します。

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

Queue Storage トリガーによって開始される次の関数は、入力テーブルから行を取得するために使用されるキューから、行キーを読み取ります。 式 {queueTrigger} は、メッセージのメタデータ (メッセージ文字列) に行キーをバインドします。

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

次のキューによってトリガーされる関数は、IEnumerable<T> として最初の5つのエンティティを返します。パーティションキーの値はキュー メッセージとして設定されます。

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

Filter のプロパティと Take のプロパティは、返されるエンティティの数を制限するために使用されます。

次の例では、テーブル ストレージ内の指定したパーティション内にある person オブジェクトの一覧を返す、HTTP によってトリガーされる関数を示します。 この例では、パーティション キーは http ルートから抽出され、tableName と connection は関数の設定からのものです。

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

TableInput 注釈では、次の例のように、要求の JSON 本文からバインドを抽出することもできます。

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

次の例では、フィルターを使用して、Azure テーブル内の特定の名前を持つ人物についてクエリを実行し、一致候補の数を 10 件の結果に制限しています。

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

次の例は、キュー トリガーを使用して 1 つのテーブル行を読み取るテーブル入力バインドを示しています。 このバインディングでは partitionKeyrowKey が指定されます。 rowKey 値 "{queueTrigger}" は、行キーがキュー メッセージ文字列から取得されることを示します。

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

次の関数では、キュー トリガーを使用して、関数への入力として 1 つのテーブル行を読み取ります。

この例では、バインド構成によってテーブルの partitionKey に明示的な値が指定され、式を使用して rowKey に渡しています。 rowKey 式の {queueTrigger} は、行キーがキュー メッセージ文字列から取得されることを示します。

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
}

run.ps1 の PowerShell コード:

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

次の関数では、HTTP トリガーを使用して、関数への入力として 1 つのテーブル行を読み取ります。

この例では、バインド構成によってテーブルの partitionKey に明示的な値が指定され、式を使用して rowKey に渡しています。 rowKey 式である {id} は、行キーが要求のルートの {id} の部分から取得されることを示します。

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
}

__init__.py ファイルの Python コード:

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

この単純なバインドでは、行キー ID を持つ行が見つからないケースをプログラムで処理できません。 より詳細なデータ選択を行う場合は、ストレージ SDK を使用します。


属性

インプロセス分離ワーカー プロセスの C# ライブラリの両方で、属性を使って関数を定義します。 C# スクリプトでは、C# スクリプト ガイドで説明されているように、代わりに function.json 構成ファイルを使用します。

C# クラス ライブラリでは、TableInputAttribute は次のプロパティをサポートしています。

属性のプロパティ 説明
TableName テーブルの名前。
PartitionKey 省略可能。 読み取るテーブル エンティティのパーティション キー。
RowKey 省略可能。 読み取るテーブル エンティティの行キー。
Take 省略可能。 IEnumerable<T> で読み取るエンティティの最大数。 RowKey とは使用できません。
Assert 省略可能。 IEnumerable<T> に読み取るエンティティの OData フィルター式。 RowKey とは使用できません。
接続 テーブル サービスへの接続方法を指定するアプリ設定または設定コレクションの名前。 「接続」を参照してください。

注釈

Java 関数ランタイム ライブラリで、その値がテーブル ストレージに由来するパラメーターで @TableInput 注釈を使用します。 この注釈は、Java のネイティブ型、POJO、または Optional<T> を使用した null 許容値で使用できます。 この注釈は、次の要素をサポートします。

要素 説明
name 関数コード内のテーブルまたはエンティティを表す変数の名前。
tableName テーブルの名前。
partitionKey 省略可能。 読み取るテーブル エンティティのパーティション キー。
rowKey 省略可能。 読み取るテーブル エンティティの行キー。
take 任意。 読み取るエンティティの最大数。
filter 任意。 テーブル入力の OData フィルター式。
connection テーブル サービスへの接続方法を指定するアプリ設定または設定コレクションの名前。 「接続」を参照してください。

構成

次の表では、input.table() メソッドに渡される options オブジェクトに対して設定できるプロパティについて説明します。

プロパティ 説明
tableName テーブルの名前。
partitionKey 省略可能。 読み取るテーブル エンティティのパーティション キー。
rowKey 省略可能。 読み取るテーブル エンティティの行キー。 take または filter と同時に使用できません。
take 任意。 返すエンティティの最大数。 rowKey とは使用できません。
filter 任意。 テーブルから返されるエンティティの OData フィルター式。 rowKey とは使用できません。
connection テーブル サービスへの接続方法を指定するアプリ設定または設定コレクションの名前。 「接続」を参照してください。

構成

次の表は、function.json ファイルで設定したバインド構成のプロパティを説明しています。

function.json のプロパティ 説明
type table に設定する必要があります。 このプロパティは、Azure Portal でバインドを作成するときに自動で設定されます。
direction in に設定する必要があります。 このプロパティは、Azure Portal でバインドを作成するときに自動で設定されます。
name 関数コード内のテーブルまたはエンティティを表す変数の名前。
tableName テーブルの名前。
partitionKey 省略可能。 読み取るテーブル エンティティのパーティション キー。
rowKey 省略可能。 読み取るテーブル エンティティの行キー。 take または filter と同時に使用できません。
take 任意。 返すエンティティの最大数。 rowKey とは使用できません。
filter 任意。 テーブルから返されるエンティティの OData フィルター式。 rowKey とは使用できません。
connection テーブル サービスへの接続方法を指定するアプリ設定または設定コレクションの名前。 「接続」を参照してください。

ローカルで開発する場合は、Values コレクション内の local.settings.json ファイルにアプリケーション設定を追加します。

つながり

connection プロパティは、アプリをテーブル サービスに接続する方法を指定する環境構成への参照です。 次が指定されている場合があります。

  • 接続文字列を含むアプリケーション設定の名前
  • 合わせて ID ベースの接続を定義する、複数のアプリケーション設定の共有のプレフィックスの名前

構成された値が、1 つの設定に完全一致し、プレフィックスがその他の設定とも一致する場合は、完全一致が使用されます。

接続文字列

Azure Table ストレージでテーブルの接続文字列を取得するには、「ストレージ アカウント アクセス キーを管理する」の手順に従います。 Azure Cosmos DB for Table のテーブルの接続文字列を取得するには、「Azure Cosmos DB for Table の FAQ」に記載されている手順に従います。

この接続文字列は、バインディング構成の connection プロパティで指定した値と同じ名前のアプリケーション設定に格納する必要があります。

アプリ設定の名前が "AzureWebJobs" で始まる場合は、ここで名前の残りの部分のみを指定できます。 たとえば、connection を "MyStorage" に設定した場合、Functions ランタイムは "AzureWebJobsMyStorage" という名前のアプリ設定を探します。 connection を空のままにした場合、Functions ランタイムは、アプリ設定内の AzureWebJobsStorage という名前の既定のストレージ接続文字列を使用します。

ID ベースの接続

Tables API 拡張機能を使っている場合は、シークレットを含む接続文字列を使う代わりに、アプリで Microsoft Entra ID を使用できます。 これは Azure Storage のテーブルにアクセスする場合にのみ適用されます。 ID を使用するには、トリガーとバインドの構成の connection プロパティにマップされる共通のプレフィックスに設定を定義します。

connection を "AzureWebJobsStorage" に設定する場合は、「ID を使用してホスト ストレージに接続する」を参照してください。 その他のすべての接続では、拡張機能に次のプロパティが必要です。

プロパティ 環境変数テンプレート 説明 値の例
テーブル サービス URI <CONNECTION_NAME_PREFIX>__tableServiceUri1 HTTPS スキームを使用して接続している Azure Storage テーブル サービスのデータ プレーン URI。 https://<storage_account_name>.table.core.windows.net

1<CONNECTION_NAME_PREFIX>__serviceUri をエイリアスとして使用できます。 両方の形式が指定された場合、tableServiceUri の形式が使用されます。 全体の接続構成が BLOB、キュー、テーブル間で使用される場合、serviceUri 形式は指定できません。

接続をカスタマイズするには、他のプロパティを設定します。 「ID ベース接続に共通のプロパティ」を参照してください。

全体の接続構成が Azure Storage 内の BLOB、キュー、テーブル間で使用される場合、serviceUri 形式は指定できません。 URI ではテーブル サービスのみを指定できます。 別の方法として、同じプレフィックスでのサービスごとに専用の URI を指定して、1 つの接続を使用できるようにすることができます。

Azure Functions サービスでホストされている場合、ID ベースの接続では、マネージド ID が使用されます。 ユーザー割り当て ID を credential および clientID プロパティで指定できますが、システム割り当て ID が既定で使用されます。 リソース ID を使用したユーザー割り当て ID の構成はサポートされていないことに注意してください。 ローカル開発などの他のコンテキストで実行する場合は、代わりに開発者 ID が使用されますが、カスタマイズすることもできます。 ID ベースの接続によるローカル開発に関するページをご覧ください。

ID にアクセス許可を付与する

使用されている ID が何であれ、目的のアクションを実行するためのアクセス許可が必要です。 ほとんどの Azure では、これはそれらのアクセス許可を提供する組み込みロールまたはカスタム ロールを使って、Azure RBAC でロールを割り当てる必要があることを意味します。

重要

すべてのコンテキストに必要ではない一部のアクセス許可がターゲット サービスによって公開される場合があります。 可能であれば、最小限の特権の原則に従い、必要な特権だけを ID に付与します。 たとえば、アプリがデータ ソースからの読み取りのみを行う必要がある場合は、読み取りアクセス許可のみを持つロールを使用します。 サービスへの書き込みも可能なロールを割り当てることは、読み取り操作に対するアクセス許可が過剰になるため、不適切です。 同様に、ロールの割り当てが、読み取る必要のあるリソースだけに限定されていることを確認する必要があります。

実行時に Azure Storage テーブル サービスへのアクセスを提供するロール割り当てを作成する必要があります。 所有者のような管理ロールでは十分ではありません。 次の表は、通常の操作で Azure Storage に対して Azure テーブルの拡張機能を使用するときに推奨される組み込みロールを示しています。 アプリケーションでは、記述したコードに基づいて追加のアクセス許可が必要になる場合があります。

[バインドの種類] 組み込みロールの例 (Azure Storage 1)
入力バインド ストレージ テーブル データ閲覧者
出力バインド ストレージ テーブル データ共同作成者

1 代わりに、アプリが Azure Cosmos DB for Table のテーブルに接続している場合、ID の使用はサポートされておらず、接続は接続文字列を使用する必要があります。

使用法

バインディングの使用方法は、拡張機能パッケージのバージョンと、関数アプリで使用される C# のモダリティによって異なり、次のいずれかになります。

分離ワーカー プロセス クラス ライブラリは、ランタイムから分離されたプロセスで実行されるコンパイル済みの C# 関数です。

バージョンを選択すると、モードとバージョンの使用状況の詳細が表示されます。

1 つのテーブル エンティティを操作する場合、Azure テーブルの入力バインドは次の型にバインドできます。

Type 説明
ITableEntity を実装する、JSON シリアル化可能な型 Functions は、エンティティを単純な従来の CLR オブジェクト (POCO) 型に逆シリアル化しようとします。 この型は、ITableEntity を実装するものか、RowKey 文字列プロパティと PartitionKey 文字列プロパティを持つものにする必要があります。
TableEntity1 エンティティを表す、ディクショナリに似た型。

クエリで複数のエンティティを操作する場合、Azure テーブルの入力バインドは次の型にバインドできます。

Type 説明
IEnumerable<T> (TITableEntity を実装します) クエリによって返されるエンティティの列挙。 各エントリは 1 つのエンティティを表します。 型 T は、ITableEntity を実装するものか、RowKey 文字列プロパティと PartitionKey 文字列プロパティを持つものにする必要があります。
TableClient1 テーブルに接続されているクライアント。 これによってテーブルの処理を最大限に制御でき、接続に十分なアクセス許可がある場合は、これを使ってテーブルに書き込むことができます。

1 これらの型を使用するには、Microsoft.Azure.Functions.Worker.Extensions.Tables 1.2.0 以降SDK 型バインドの一般的な依存関係に関する記事を参照する必要があります。

TableInput 属性を使用すると、関数をトリガーしたテーブル行にアクセスできます。

context.extraInputs.get() を使用して入力行データを取得します。

データは、name ファイルの name キーによって指定された入力パラメーターに渡されます。 partitionKeyrowKey を指定すると、特定のレコードをフィルター処理できます。

テーブル データは、JSON 文字列として関数に渡されます。 入力json.loadsに示されているように json.loads を呼び出してメッセージを逆シリアル化します。

具体的な使用方法の詳細については、「例」を参照してください。

次のステップ