yotiky Tech Blog

とあるエンジニアの備忘録

Azure Functions で Azure Cosmos DB (Table) を操作する

目次

検証環境

  • Azure Functions v3
  • Microsoft.Azure.Cosmos.Table v1.0.8

古いライブラリに注意

  • WindowsAzure.Storage は非推奨
  • Microsoft.Azure.CosmosDB.Table はまもなく非推奨

実装

NuGet でライブラリをインストールする。

using Microsoft.Azure.Cosmos.Table;

データ定義は、TableEntity を継承したクラスを作成する。 取得時にパラメータなしのコンストラクタが必要になる。

public class CustomerEntity : TableEntity
{
    public CustomerEntity() { }
    public CustomerEntity(string lastName, string firstName)
    {
        PartitionKey = lastName;
        RowKey = firstName;
    }

    public string Email { get; set; }
    public string PhoneNumber { get; set; }
}

CloudTableインスタンスを取得する。

var connectionString = "ConnectionString";
var tableName = "TableA";

var storageAccount = CloudStorageAccount.Parse(connectionString);
var tableClient = storageAccount.CreateCloudTableClient();
var cloudTalbe = tableClient.GetTableReference(tableName);

テーブル作成

// なければ作成する
await table.CreateIfNotExistsAsync(IndexingMode.Consistent, throughput: 400, null, CancellationToken.None);

プロビジョニングされたスループットの場合、throughput を指定せずに作成すると 800 で作成されてしまうので注意。最低コストの2倍発生する。 IndexingModedefaultTimeToLive はこの指定で手動で作成した時のデフォルト値と同じになる。

テーブルに設定されたスループットは、ポータル上の下図から確認できる。 f:id:yotiky:20210227183357p:plain

挿入

1件挿入する場合。

var entity = new CustomerEntity("Tanaka", "Taro")
{ 
    Email = "aaa", 
    PhoneNumber = "001"
};

await cloudTalbe.ExecuteAsync(TableOperation.InsertOrReplace(entity));

まとめて挿入する場合。

var entities = new[]
{
    new CustomerEntity("Tanaka", "Taro"){ Email = "aaa", PhoneNumber = "001"},
    new CustomerEntity("Tanaka", "Jiro"){ Email = "bbb", PhoneNumber = "002"},
};

var operation = new TableBatchOperation();
foreach (var entity in entities)
{
    operation.Add(TableOperation.InsertOrReplace(entity));
}

await cloudTalbe.ExecuteBatchAsync(operation);

取得

PartitionKeyとRowKeyを指定して1件取得する場合。

var entity = new CustomerEntity("Tanaka", "Taro")
{ 
    Email = "aaa", 
    PhoneNumber = "001"
};

var tableResult = await cloudTalbe.ExecuteAsync(TableOperation.Retrieve<CustomerEntity>(entity.PartitionKey, entity.RowKey));
var result = tableResult.Result as CustomerEntity;

クエリを使う場合。

var entity = new CustomerEntity("Tanaka", "Taro")
{ 
    Email = "aaa", 
    PhoneNumber = "001"
};


var query = new TableQuery<CustomerEntity>();
query.FilterString = TableQuery.CombineFilters(
    TableQuery.GenerateFilterCondition(nameof(CustomerEntity.PartitionKey), QueryComparisons.Equal, entity.PartitionKey),
    TableOperators.And,
    TableQuery.GenerateFilterCondition(nameof(CustomerEntity.RowKey), QueryComparisons.Equal, entity.RowKey));

var tableResult = await cloudTalbe.ExecuteQuerySegmentedAsync(query, null);
var results = tableResult.Results;

ソートしたい場合。

var where = TableQuery.GenerateFilterCondition(nameof(CustomerEntity.PartitionKey), QueryComparisons.Equal, entity.PartitionKey);

var query = new TableQuery<CustomerEntity>()
    .Where(where)
    .Order(nameof(CustomerEntity.Timestamp));

var tableResult = await cloudTalbe.ExecuteQuerySegmentedAsync(query, null);

cloudTalbe.CreateQuery<CustomerEntity>() を使おうとすると NotSupportedException が発生するので注意*1

削除

取得時の Entity が書き換わってないかチェックして削除する場合。

await cloudTalbe.ExecuteAsync(TableOperation.Delete(entity));

気にせず削除する場合は ETag にワイルドカードを使う。

var entity = new CustomerEntity("Tanaka", "Taro");
entity.ETag = "*";
await cloudTalbe.ExecuteAsync(TableOperation.Delete(entity));

補足

パフォーマンスや料金の基準となる RU だが、クエリでの使用量を確認するにはいくつかの方法がある。 ただ Table API で用意されているのは今の所 SDK を使う方法しかない。

CosmosDBのリソース開いて Insights(プレビュー) で統計情報は見れる。(Appliction Insights ではない)

f:id:yotiky:20210327175828p:plain:w300

参考

関連記事