ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

Azure Storage Client Library 1.7 を 4.3 に移行する( Table 編 )

Storage Client Library 1.7 を 最新版(4.3)に移行する際のポイントをまとめます。この記事では、Table Storage について記載します。それ以外については、記事を分けました。

Entity

#Version 1.7
public class Person : TableServiceEntity
#Version 4.3
public class Person : TableEntity

Table Storage を操作する Entity は、TableEntity を継承する必要があります。TableEntity を継承したクラスは、Serializable や DataContract の属性によるシリアライズができません。どうしてもシリアライズしたい場合は、TableEntity の代わりとなる ITableEntity を継承したクラスを自前で実装するなどの対応が必要です。

Table の作成と削除

#Version 1.7
// Create
tableClient.CreateTableIfNotExist("Person");
// Delete
tableClient.DeleteTableIfExist("Person");
// Exist
var isExists = tableClient.DoesTableExist("Person");
#Version 4.3
// Create
CloudTable table = tableClient.GetTableReference("Person");
await table.CreateIfNotExistsAsync();
// Delete
await table.DeleteIfExistsAsync();
// Exist
var isExists = await table.ExistsAsync();

TableClient ではなく、CloudTable のインスタンスを取得して処理します。メソッド名が Exists となり、「s」が付加されています。

Entity の追加

#Version 1.7
var person = new Person{ PartitionKey = "p1", RowKey = "r1", FirstName = "Aaron", LastName = "Ramsey" };
var tableContext = tableClient.GetDataServiceContext();
tableContext.AddObject("Person", person);
tableContext.SaveChanges();
#Version 4.3
var person = new Person{ PartitionKey = "p1", RowKey = "r1", FirstName = "Aaron", LastName = "Ramsey" };
var table = tableClient.GetTableReference("Person");
var operation = TableOperation.Insert(person);
await table.ExecuteAsync(operation);

Entity の操作は、Operation を決めて Execute() メソッドを実行する方法に統一されます。

Entity の更新

#Version 1.7
var tableContext = tableClient.GetDataServiceContext();
tableContext.UpdateObject("Person", person);
tableContext.SaveChanges();
#Version 4.3
var table = tableClient.GetTableReference("Person");
var operation = TableOperation.Replace(person);
await table.ExecuteAsync(operation);

Entity の操作は、Operation を決めて Execute() メソッドを実行する方法に統一されます。

Entity の削除

#Version 1.7
var tableContext = tableClient.GetDataServiceContext();
tableContext.DeleteObject("Person", person);
tableContext.SaveChanges();
#Version 4.3
var table = tableClient.GetTableReference("Person");
var operation = TableOperation.Delete(person);
await table.ExecuteAsync(operation);

Entity の操作は、Operation を決めて Execute() メソッドを実行する方法に統一されます。

Entity の単一検索

#Version 1.7
var tableContext = tableClient.GetDataServiceContext();
var result = (from entity in tableContext.CreateQuery("Person")
                     where entity.PartitionKey.Equals("p1") && entity.RowKey.Equals("r1")
                     select entity).SingleOrDefault();
#Version 4.3
var table = tableClient.GetTableReference("Person");
var operation = TableOperation.Retrieve("p1", "r1");
var result = await table.ExecuteAsync(operation).Result;

Entity の操作は、Operation を決めて Execute() メソッドを実行する方法に統一されます。

Entity の条件検索

#Version 1.7
var tableContext = tableClient.GetDataServiceContext();
var result = (from entity in tableContext.CreateQuery("Person")
                     where entity.PartitionKey.Equals("p1") && entity.LastName.Equals("Ramsey")
                     select entity).ToList();
#Version 4.3
var table = tableClient.GetTableReference("Person");
var query = new TableQuery()
                            .Where(TableQuery.CombineFilters(
                            TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "p1"),
                            TableOperators.And,
                            TableQuery.GenerateFilterCondition("LastName", QueryComparisons.Equal, "Ramsey")));
var result = table.ExecuteQuery(query).ToList();

TableQuery に対して、クエリを作って ExecuteQuery() メソッドを実行します。Continuation Tokens が考慮されているので、1,000件以上でも一括で取得することが可能です。

Entity のバッチ処理

#Version 1.7
var person1 = new Person{ PartitionKey = "p1", RowKey = "r1", FirstName = "Aaron", LastName = "Ramsey" };
var person2 = new Person{ PartitionKey = "p1", RowKey = "r2", FirstName = "Jack", LastName = "Wilshere" };
var tableContext = tableClient.GetDataServiceContext();
tableContext.AddObject("Person", person1);
tableContext.AddObject("Person", person2);
tableContext.SaveChanges();
#Version 4.3
var person1 = new Person{ PartitionKey = "p1", RowKey = "r1", FirstName = "Aaron", LastName = "Ramsey" };
var person2 = new Person{ PartitionKey = "p1", RowKey = "r2", FirstName = "Jack" , LastName = "Wilshere" };
var table = tableClient.GetTableReference("Person");
var batchOperation = new TableBatchOperation();
batchOperation.Insert(person1);
batchOperation.Insert(person2);
await table.ExecuteBatchAsync(batchOperation);

TableBatchOperation を作って、ExecuteBatch() メソッドを実行します。TableBatchOperation には、同一パーティション内で最大 100 Entity(4MB)の制約があります。

Table リストの取得

#Version 1.7
List result = tableClient.ListTables().ToList();
#Version 4.3
List result = tableClient.ListTables().Select(x => x.Name).ToList();

ListTable() メソッドの戻り値が CloudTable 型に変更されているため、テーブル名は Name プロパティから取得します。

Table のコピー

#Version 1.7
var tableContext = tableClient.GetDataServiceContext();
var tableContext2 = tableClient.GetDataServiceContext();
foreach (var entity in tableContext.CreateQuery<object>("Person"))
{
    tableContext2.AddObject("Person2", entity);
}
tableContext2.SaveChanges();
#Version 4.3
var table = tableClient.GetTableReference("Person");
var table2 = tableClient.GetTableReference("Person2");
foreach (var entity in table.ExecuteQuery(new TableQuery()))
{
    var operation = TableOperation.Insert(entity);
    await table2.ExecuteAsync(operation);
}

DynamicTableEntity を利用することで、Table ごとの Entity を使わずに操作できて便利です。