Table Storage でバッチ処理
Azure の Table Storage を .NET から扱う場合は Microsoft.WindowsAzure.Storage
1 が利用できる。その中でバッチ処理についてメモ。
単一のテーブルにバッチ処理を行いたい場合は TableBatchOperation
クラスを使う。
var entities = GetEntities(); var operations = new TableBatchOperation(); foreach(var entity in entities) { operations.Add(TableOperation.Add(entity)); } await table.ExecuteBatchAsync(operations, cancellationToken);
Atomicity は担保されているらしい。なので 1 件でも失敗したらロールバックされるような動きになる。 参考
パフォーマンスもこの方がいいらしい。
また TableBatchOperation
は IList<T>
の実装なので実行順序は保証されている。はず。よね?
注意しときたいのは、このとき entities が空だと ExecuteBatchAsync
で空振り......ではなく StorageException を吐く。 TableBatchOperation
にオペレーションを詰める前に分岐させてスキップしておくのが良さげ。
var entities = GetEntities(); if(entities.Length > 0) { var operations = new TableBatchOperation(); foreach(var entity in entities) { operations.Add(TableOperation.Add(entity)); } await table.ExecuteBatchAsync(operations, cancellationToken); }
また、 1 バッチオペレーションでは Insert / Delete 同時に実行できるが、同一エンティティを Insert / Delete しようとすると死ぬ。意図的にこんなことをしようとすることはないだろうけど、結果的にそうなっちゃったってことは起こり得るかも。
try { var operation = new TableBatchOperation { TableOperation.Insert(new UserMappingSet {PartitionKey = "hoge", RowKey = "fuga"}), TableOperation.Delete(new UserMappingSet {PartitionKey = "hoge", RowKey = "fuga", ETag = "*"}) }; await table.ExecuteBatchAsync(operation, cancellationToken); } catch (StorageException ex) { // "1:One of the request inputs is not valid. ..." log.Error(e.RequestInformation.ExtendedErrorInformation.ErrorMessage) }
なお複数テーブルに対するトランザクション処理的なものは用意されていない。 Entity Group Transactions というのが使えそうな気配がするが、少なくとも SDK にそれっぽいものがなく、 REST API 専用なのかな?
-
.NET を使用して Azure Table Storage と Azure Cosmos DB Table API を使用する | Microsoft Docs によると 「
Microsoft.Azure.Storage.Common
を使え」らしいが、 NuGet で落とそうとすると preview しかなかったりして謎。↩