Amazon DynamoDB NoSQL データベースの使用 - AWS SDK for .NET

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Amazon DynamoDB NoSQL データベースの使用

注記

これらのトピックのプログラミングモデルは.NET Framework と.NET (Core) の両方に存在しますが、呼び出し規則は同期か非同期かで異なります。

は、 が提供する高速な NoSQL データベースサービスである Amazon DynamoDB AWS SDK for .NET をサポートしています AWS。SDK では、DynamoDB との通信用に 3 つのプログラムモデルが提供されています。低レベルモデル、ドキュメントモデル、オブジェクト永続性モデルです。

以下では、これらのモデルとその API について紹介し、それぞれの使用方法と用途の例を示します。また、 AWS SDK for .NETでの追加の DynamoDB プログラミングリソースへのリンクも提供します。

低レベルモデル

低レベルプログラミングモデルは、DynamoDB サービスの直接呼び出しをラップします。このモデルには、Amazon.DynamoDBv2 名前空間からアクセスします。

低レベルモデルは、3 つのモデルの中で最も多くのコードを記述する必要があります。例えば、.NET データ型を DynamoDB の同等の型に変換する必要があります。ただし、このモデルを使用するとほとんどの機能にアクセスできます。

以下の例では、低レベルモデルを使用して DynamoDB でのテーブルの作成、テーブルの変更、テーブルへの項目の挿入を行う方法を示します。

テーブルの作成

次の例では、CreateTable クラスの AmazonDynamoDBClient メソッドを使用してテーブルを作成します。CreateTable メソッドでは、必要な項目属性名、プライマリキーの定義、スループット容量などの特性を含む CreateTableRequest クラスのインスタンスを使用します。CreateTable メソッドは、CreateTableResponse クラスのインスタンスを返します。

// using Amazon.DynamoDBv2; // using Amazon.DynamoDBv2.Model; var client = new AmazonDynamoDBClient(); Console.WriteLine("Getting list of tables"); List<string> currentTables = client.ListTables().TableNames; Console.WriteLine("Number of tables: " + currentTables.Count); if (!currentTables.Contains("AnimalsInventory")) { var request = new CreateTableRequest { TableName = "AnimalsInventory", AttributeDefinitions = new List<AttributeDefinition> { new AttributeDefinition { AttributeName = "Id", // "S" = string, "N" = number, and so on. AttributeType = "N" }, new AttributeDefinition { AttributeName = "Type", AttributeType = "S" } }, KeySchema = new List<KeySchemaElement> { new KeySchemaElement { AttributeName = "Id", // "HASH" = hash key, "RANGE" = range key. KeyType = "HASH" }, new KeySchemaElement { AttributeName = "Type", KeyType = "RANGE" }, }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 10, WriteCapacityUnits = 5 }, }; var response = client.CreateTable(request); Console.WriteLine("Table created with request ID: " + response.ResponseMetadata.RequestId); }

テーブルを変更する準備が整っていることの確認

テーブルを変更または修正する前に、テーブルを変更する準備が整っていることを確認する必要があります。次の例では、低レベルモデルを使用して DynamoDB のテーブルの準備が整っていることを確認する方法を示します。この例では、チェック対象のテーブルは DescribeTable クラスの AmazonDynamoDBClient メソッドを使用して参照されています。5 秒ごとに、コードはテーブルの TableStatus プロパティの値を調べます。ステータスが ACTIVE に設定されると、テーブルは変更できる状態です。

// using Amazon.DynamoDBv2; // using Amazon.DynamoDBv2.Model; var client = new AmazonDynamoDBClient(); var status = ""; do { // Wait 5 seconds before checking (again). System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5)); try { var response = client.DescribeTable(new DescribeTableRequest { TableName = "AnimalsInventory" }); Console.WriteLine("Table = {0}, Status = {1}", response.Table.TableName, response.Table.TableStatus); status = response.Table.TableStatus; } catch (ResourceNotFoundException) { // DescribeTable is eventually consistent. So you might // get resource not found. } } while (status != TableStatus.ACTIVE);

テーブルへの項目の挿入

次の例では、低レベルモデルを使用して DynamoDB のテーブルに 2 つの項目を挿入します。各項目は、PutItem クラスのインスタンスを使用して、AmazonDynamoDBClient クラスの PutItemRequest メソッドによって挿入されます。PutItemRequest クラスの 2 つのインスタンスはそれぞれ、項目を挿入するテーブルの名前と一連の項目属性値を取得します。

// using Amazon.DynamoDBv2; // using Amazon.DynamoDBv2.Model; var client = new AmazonDynamoDBClient(); var request1 = new PutItemRequest { TableName = "AnimalsInventory", Item = new Dictionary<string, AttributeValue> { { "Id", new AttributeValue { N = "1" }}, { "Type", new AttributeValue { S = "Dog" }}, { "Name", new AttributeValue { S = "Fido" }} } }; var request2 = new PutItemRequest { TableName = "AnimalsInventory", Item = new Dictionary<string, AttributeValue> { { "Id", new AttributeValue { N = "2" }}, { "Type", new AttributeValue { S = "Cat" }}, { "Name", new AttributeValue { S = "Patches" }} } }; client.PutItem(request1); client.PutItem(request2);

ドキュメントモデル

ドキュメントプログラミングモデルは、DynamoDB のデータを操作する簡単な手段を提供します。このモデルは、特にテーブルおよびテーブル内の項目にアクセスすることを目的に作られています。このモデルには、Amazon.DynamoDBv2. DocumentModel名前空間からアクセスします。

低レベルプログラミングモデルと比べると、ドキュメントモデルの方が DynamoDB データに対するコーディングが容易です。例えば、多くの .NET データ型を DynamoDB の同等のデータ型に変換する必要はありません。ただし、このモデルでは、低レベルプログラミングモデルほど多くの機能にはアクセスできません。たとえば、このモデルを使用して、テーブルの項目を作成、取得、更新、削除することはできます。しかし、テーブルを作成するには、低レベルモデルを使用する必要があります。オブジェクト永続性モデルと比較すると、このモデルの方が .NET オブジェクトを保存、ロード、クエリするために多くのコードを作成する必要があります。

DynamoDB ドキュメントプログラミングモデルの詳細については、Amazon DynamoDB デベロッパーガイドの「.NET: ドキュメントモデル」を参照してください。

以下のセクションでは、目的の DynamoDB テーブルの表現を作成する方法と、ドキュメントモデルを使用してテーブルに項目を挿入し、テーブルから項目を取得する方法の例を示します。

表の表現の作成

ドキュメントモデルを使用してデータオペレーションを実行するには、最初に メソッドを呼び出して、特定のテーブルを表す Tableクラスのインスタンスを作成します。これには、主に 2 つの方法があります。

LoadTable メソッド

1 つ目のメカニズムは、次の例のように、Tableクラスの静的LoadTableメソッドの 1 つを使用することです。

var client = new AmazonDynamoDBClient(); Table table = Table.LoadTable(client, "Reply");
注記

このメカニズムは機能しますが、特定の条件下では、コールドスタートやスレッドプールの動作が原因で、レイテンシーが増えたり、デッドロックが発生したりすることがあります。これらの動作の詳細については、ブログ記事「AWS SDK for .NETのDynamoDB 初期化パターンの改善」を参照してください。

TableBuilder

代替メカニズムである TableBuilder クラスは、 AWSSDK.DynamoDBv2 NuGet package のバージョン 3.7.203 で導入されました。このメカニズムでは、特定の暗黙的なメソッド呼び出し (具体的にはDescribeTableメソッド) を削除することで、上記の動作に対処できます。このメカニズムは、次の例のような方法で使用されます。

var client = new AmazonDynamoDBClient(); var table = new TableBuilder(client, "Reply") .AddHashKey("Id", DynamoDBEntryType.String) .AddRangeKey("ReplyDateTime", DynamoDBEntryType.String) .AddGlobalSecondaryIndex("PostedBy-Message-index", "Author", DynamoDBEntryType.String, "Message", DynamoDBEntryType.String) .Build();

この代替メカニズムの詳細については、ブログ記事「 AWS SDK for .NETの DynamoDB 初期化パターンの改善」をもう一度参照してください。

テーブルへの項目の挿入

次の例では、PutItemAsync クラスの Table メソッドを使用してテーブルにリプライを挿入しています。PutItemAsync メソッドは、Document クラスのインスタンスを受け取ります。Document クラスは、初期化された属性の単純なコレクションです。

using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DocumentModel; // Create a representation of the "Reply" table // by using one of the mechanisms described previously. // Then, add a reply to the table. var newReply = new Document(); newReply["Id"] = Guid.NewGuid().ToString(); newReply["ReplyDateTime"] = DateTime.UtcNow; newReply["PostedBy"] = "Author1"; newReply["Message"] = "Thank you!"; await table.PutItemAsync(newReply);

テーブルからの項目の取得

次の例では、GetItemAsync クラスの Table メソッドを使用してリプライを取得しています。取得する返信を決定するために、 GetItemAsyncメソッドはターゲット返信の hash-and-range プライマリキーを使用します。

using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DocumentModel; // Create a representation of the "Reply" table // by using one of the mechanisms described previously. // Then, get a reply from the table // where "guid" is the hash key and "datetime" is the range key. var reply = await table.GetItemAsync(guid, datetime); Console.WriteLine("Id = " + reply["Id"]); Console.WriteLine("ReplyDateTime = " + reply["ReplyDateTime"]); Console.WriteLine("PostedBy = " + reply["PostedBy"]); Console.WriteLine("Message = " + reply["Message"]);

前述の例では、テーブル値を WriteLine メソッドの文字列に暗黙的に変換しています。DynamoDBEntryクラスのさまざまな 「As[type]」 メソッドを使用すると、明示的に変換できます。たとえば、AsGuid() メソッドを使用して、Id の値を Primitive データ型から GUID に明示的に変換できます。

var guid = reply["Id"].AsGuid();

オブジェクト永続性モデル

オブジェクト永続性プログラミングは、特に DynamoDB での .NET オブジェクトの保存、ロード、クエリを目的として作られています。このモデルには、Amazon.DynamoDBv2. DataModel名前空間からアクセスします。

3 つのモデルの中で、オブジェクト永続性モデルは、DynamoDB データの保存、ロード、クエリに関してはコーディングが最も簡単です。例えば、DynamoDB のデータ型を直接操作できます。ただし、このモデルでアクセスできるのは、DynamoDB に .NET オブジェクトを保存、ロード、クエリする操作だけです。たとえば、このモデルを使用して、テーブルの項目を作成、取得、更新、削除することはできます。ただし、最初に低レベルモデルを使用してテーブルを作成してから、このモデルを使用して .NET クラスをテーブルにマッピングする必要があります。

DynamoDB オブジェクト永続性プログラミングモデルの詳細については、「Amazon DynamoDB デベロッパーガイド」の「.NET: オブジェクト永続性モデル」を参照してください。

次の例は、DynamoDB 項目を表す .NET クラスを定義する方法、.NET クラスのインスタンスを使用して項目を DynamoDB テーブルに挿入する方法、.NET クラスのインスタンスを使用してテーブルから項目を取得する方法を示しています。

テーブルで項目を表す .NET クラスの定義

次のクラス定義の例では、 DynamoDBTable 属性はテーブル名を指定し、 属性DynamoDBHashKeyDynamoDBRangeKey 属性はテーブルの hash-and-range プライマリキーをモデル化します。DynamoDBGlobalSecondaryIndexHashKey属性は、特定の作成者による返信のクエリを作成できるように定義されています。

using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DataModel; [DynamoDBTable("Reply")] public class Reply { [DynamoDBHashKey] public string Id { get; set; } [DynamoDBRangeKey(StoreAsEpoch = false)] public DateTime ReplyDateTime { get; set; } [DynamoDBGlobalSecondaryIndexHashKey("PostedBy-Message-Index", AttributeName ="PostedBy")] public string Author { get; set; } [DynamoDBGlobalSecondaryIndexRangeKey("PostedBy-Message-Index")] public string Message { get; set; } }

オブジェクト永続性モデルのコンテキストを作成します。

DynamoDB のオブジェクト永続プログラミングモデルを使用するには、コンテキストを作成する必要があります。このクラスから DynamoDB に接続して、テーブルにアクセスし、各種のオペレーションとクエリを実行することができます。

基本コンテキスト

次の例は、最も基本的なコンテキストを作成する方法を示しています。

using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DataModel; var client = new AmazonDynamoDBClient(); var context = new DynamoDBContext(client);

DisableFetchingTableMetadata プロパティを含むコンテキスト

次の例は、DescribeTableメソッドが暗黙的に呼び出されないように、DynamoDBContextConfigクラスのDisableFetchingTableMetadataプロパティを追加で設定する方法を示しています。

using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DataModel; var client = new AmazonDynamoDBClient(); var context = new DynamoDBContext(client, new DynamoDBContextConfig { DisableFetchingTableMetadata = true });

最初の例のようにDisableFetchingTableMetadataプロパティが false (デフォルト) に設定されている場合は、テーブル項目のキーとインデックスの構造を記述する属性をReplyクラスから省略できます。代わりに、これらの属性はDescribeTableメソッドを暗黙的に呼び出すことで推測されます。2 番目の例に示すように、 DisableFetchingTableMetadatatrue に設定されている場合、SaveAsyncQueryAsync などのオブジェクト永続モデルのメソッドは、Reply クラスで定義された属性に完全に依存します。この場合、DescribeTableメソッドの呼び出しは行われません。

注記

特定の条件下では、コールドスタートやスレッドプールの動作が原因で、DescribeTableメソッドを呼び出すとレイテンシーが増えたり、デッドロックが発生したりすることがあります。このため、そのメソッドの呼び出しは避けたほうが有利な場合があります。

これらの動作の詳細については、ブログ記事「 AWS SDK for .NETのDynamoDB 初期化パターンの改善」を参照してください。

.NET クラスのインスタンスの使用によるテーブルへの項目の挿入

上の例では、項目は DynamoDBContext クラスの SaveAsync メソッドによって挿入されます。このメソッドは、項目を表す .NET クラスの初期化されたインスタンスを受け取ります

using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DataModel; // Create an appropriate context for the object persistence programming model, // examples of which have been described earlier. // Create an object that represents the new item. var reply = new Reply() { Id = Guid.NewGuid().ToString(), ReplyDateTime = DateTime.UtcNow, Author = "Author1", Message = "Thank you!" }; // Insert the item into the table. await context.SaveAsync<Reply>(reply, new DynamoDBOperationConfig { IndexName = "PostedBy-Message-index" });

.NET クラスのインスタンスを使用してテーブルから項目を取得する

この例では、DynamoDBContextクラスのQueryAsyncメソッドを使用して「Author1」のすべてのレコードを検索するクエリを作成します。次に、クエリのGetNextSetAsyncメソッドを使用して項目が取得されます。

using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DataModel; // Create an appropriate context for the object persistence programming model, // examples of which have been described earlier. // Construct a query that finds all replies by a specific author. var query = context.QueryAsync<Reply>("Author1", new DynamoDBOperationConfig { IndexName = "PostedBy-Message-index" }); // Display the result. var set = await query.GetNextSetAsync(); foreach (var item in set) { Console.WriteLine("Id = " + item.Id); Console.WriteLine("ReplyDateTime = " + item.ReplyDateTime); Console.WriteLine("PostedBy = " + item.Author); Console.WriteLine("Message = " + item.Message); }

オブジェクト永続モデルに関する追加情報

上記の例と説明には、DisableFetchingTableMetadataというDynamoDBContextクラスのプロパティが含まれている場合があります。 AWSSDK.DynamoDBv2 NuGet package のバージョン 3.7.203 で導入されたこのプロパティを使用すると、コールドスタートとスレッドプールの動作が原因でレイテンシーやデッドロックがさらに発生する可能性のある特定の条件を回避できます。詳細については、ブログ記事「 AWS SDK for .NETのDynamoDB 初期化パターンの改善」を参照してください。

このプロパティに関する追加情報は次のとおりです。

  • .NET Framework を使用している場合は、このプロパティをapp.configまたはweb.configファイルにグローバルに設定できます。

  • このプロパティは、次の例に示すように、AWSConfigsDynamoDBクラスを使用してグローバルに設定できます。

    // Set the DisableFetchingTableMetadata property globally // before constructing any context objects. AWSConfigsDynamoDB.Context.DisableFetchingTableMetadata = true; var client = new AmazonDynamoDBClient(); var context = new DynamoDBContext(client);
  • クラスが依存関係で定義されている場合など、DynamoDB 属性を.NET クラスに追加できない場合があります。このような場合でも、DisableFetchingTableMetadataプロパティを利用することは可能です。そのためには、DisableFetchingTableMetadataプロパティに加えてTableBuilderクラスも使用します。TableBuilder クラスは、 AWSSDK.DynamoDBv2 NuGet package のバージョン 3.7.203 でも導入されました。

    // Set the DisableFetchingTableMetadata property globally // before constructing any context objects. AWSConfigsDynamoDB.Context.DisableFetchingTableMetadata = true; var client = new AmazonDynamoDBClient(); var context = new DynamoDBContext(client); var table = new TableBuilder(client, "Reply") .AddHashKey("Id", DynamoDBEntryType.String) .AddRangeKey("ReplyDateTime", DynamoDBEntryType.String) .AddGlobalSecondaryIndex("PostedBy-Message-index", "Author", DynamoDBEntryType.String, "Message", DynamoDBEntryType.String) .Build(); // This registers the "Reply" table we constructed via the builder. context.RegisterTableDefinition(table); // Now operations like this will work, // even if the Reply class was not annotated with this index. var query = context.QueryAsync<Reply>("Author1", new DynamoDBOperationConfig() { IndexName = "PostedBy-Message-index" });

詳細情報

AWS SDK for .NET を使用して DynamoDB の情報と例をプログラムする**

低レベルモデル情報と例

ドキュメントモデル情報と例

オブジェクト永続性モデル情報と例