AWS SDK for .NET を使った DynamoDB へのアクセス方法

# AmazonDynamoDBClient を使ったアクセス

- DynamoDBの開発ガイドのいわゆる[チュートリアル](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html)で紹介されているやり方です
- 取得できるItemsのクラスが```List<Dictionary<string, AttributeValue>>```でORMを自身で行う必要があります

```cs
// dotnet add package AWSSDK.DynamoDBv2
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var client = new AmazonDynamoDBClient();
        var tableName = "SampleTable2";
        var req = new ScanRequest(tableName);
        var resp = await client.ScanAsync(req);
        var items = resp.Items;
    }
}
```

# DynamoDBContext を使ったアクセス

- これもDynamoDBの開発ガイドにて[オブジェクト永続性モデルを使用したやり方](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DynamoDBContext.QueryScan.html)として紹介されています
- ScanAsync処理時に型パラメータとしてマッピングするクラスを指定することでマッピングしてくれます

```cs
// dotnet add package AWSSDK.DynamoDBv2
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var client = new AmazonDynamoDBClient();
        var context = new DynamoDBContext(client);
        var items = await context.ScanAsync<SampleTableItem>(null).GetRemainingAsync();
    }
}

[DynamoDBTable("SampleTable")]
class SampleTableItem
{
    // PartitionKey = user_id (String)
    // SortKey = item_id (String)

    [DynamoDBHashKey("user_id")]
    public string UserId { get; set; }

    [DynamoDBRangeKey("item_id")]
    public string ItemId { get; set; }
}
```

## DynamoDBContext使用時のテーブル名の指定方法

- 基本的に、マッピング先のクラスにDynamoDBTable属性を付け、その引数でテーブル名を指定します
- しかし、AWSConfigsDynamoDB.Context.AddMappingメソッドを使用することでもテーブル名を指定することができます
- テーブル名を環境変数や設定ファイル等から取得して設定したい場合はこの方法で行うのが良いかと思います

```cs
// dotnet add package AWSSDK.DynamoDBv2
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Util;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var client = new AmazonDynamoDBClient();
        var context = new DynamoDBContext(client);
        AWSConfigsDynamoDB.Context.AddMapping(new TypeMapping(typeof(SampleTableItem), "SampleTable"));
        var items = await context.ScanAsync<SampleTableItem>(null).GetRemainingAsync();
    }
}

class SampleTableItem
{
    // PartitionKey = user_id (String)
    // SortKey = item_id (String)

    [DynamoDBHashKey("user_id")]
    public string UserId { get; set; }

    [DynamoDBRangeKey("item_id")]
    public string ItemId { get; set; }
}
```

- ちなみにテーブル名を指定していない場合は、型パラメータで指定したクラスの名前がテーブル名として使用されます
- 以下の場合、"SampleTableItem"がScan先のテーブル名となります

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
var items = await context.ScanAsync<SampleTableItem>(null).GetRemainingAsync();

class SampleTableItem
{
    public string UserId { get; set; }
    public string ItemId { get; set; }
}
```

## DynamoDBContext使用のサンプルコード

```cs
using System;
using System.Linq;
using System.Threading.Tasks;

// dotnet add package AWSSDK.DynamoDBv2
using Amazon;
using Amazon.Util;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

class Program
{
    static async Task Main()
    {
        var client = new AmazonDynamoDBClient();
        var context = new DynamoDBContext(client);
        AWSConfigsDynamoDB.Context.AddMapping(new TypeMapping(typeof(SampleTableData), "SampleTable"));

        //
        // データの追加 (PutItem処理)
        //
        var item = new SampleTableData
        {
            PartitionKey = 0,
            SortKey = "SK0",
            Property1 = DateTime.Now
        };
        await context.SaveAsync(item);

        //
        // 複数データの追加 (BatchWriteItem処理)
        //
        var batchWrite = context.CreateBatchWrite<SampleTableData>();
        var items = Enumerable.Range(1, 9).Select(i => new SampleTableData
        {
            PartitionKey = 0,
            SortKey = "SK" + i,
            Property1 = DateTime.Now
        });
        batchWrite.AddPutItems(items);
        await batchWrite.ExecuteAsync();

        //
        // データの取得 (Query処理)
        //
        const int scanPartitionKey = 0;
        var queriedItems = await context.QueryAsync<SampleTableData>(scanPartitionKey).GetRemainingAsync();

        //
        // データの削除 (DeleteItem処理)
        //
        await context.DeleteAsync(queriedItems.First());

        //
        // 複数データの削除 (DeleteItem処理)
        //
        var batchDelete = context.CreateBatchWrite<SampleTableData>();
        batchDelete.AddDeleteItems(queriedItems.Skip(1).Take(4));
        await batchDelete.ExecuteAsync();
    }

    class SampleTableData
    {
        [DynamoDBHashKey("PK")]
        public int PartitionKey { get; set; }

        [DynamoDBRangeKey("SK")]
        public string SortKey { get; set; }

        [DynamoDBProperty("Property1")]
        public DateTime Property1 { get; set; }
    }
}
```