Alexaスキル（C#）からDynamoDBにアクセスするには？（データの追加）

#はじめに
[C#でDynamoDBにテーブルを作りました](https://qiita.com/shuhey/items/cb73812986614af629b3)。

今回はそこにデータを追加してみます。

#データの追加の流れ
テーブルにデータの追加を行うには`AmazonDynamoDBClient`クラスの`PutItemAsync`メソッドを使用します。
`PutItemAsync`メソッドに`PutItemRequest`クラスのインスタンスを渡すと、そのインスタンスに入れたデータを指定したテーブルに入れることができます。

ですので流れは以下のとおりになります。

1. `PutItemRequest`のインスタンスにテーブル名と各カラムのデータを登録
2. `PutItemAsync`メソッドに`PutItemRequest`インスタンスを引数として渡して実行

ソースコードはこんな感じです。

```csharp
            //データを挿入するリクエストを構築
            var request = new PutItemRequest
            {
                //追加先のテーブル名を指定
                TableName = tableName,
                //各カラムに入れるデータを指定
                Item = new Dictionary<string, AttributeValue>
                {
                    //「ThisIsId」カラムに「2」という数値を入れる
                    {"ThisIsId",new AttributeValue{N="2"} },
                    //「ThisIsSomething」カラムに「5」という数値を入れる
                    {"ThisIsSomething",new AttributeValue{N="5"} }
                }
            };

            var client = AmazonDynamoDBClient();

            //目的のテーブルに所定のデータを追加
            var result = client.PutItemAsync(request).Result;
```

まず、リクエストの構築です。
ここでカラムに入れる値を指定してます。
その中で「N="2"」などとしていますが、これは数値としての「2」を入れるという意味です。
「N」はデータの種類を表しているということですね。
「N」の他にも「S：文字列（String）」や「SS：文字列のリスト」、「NS：数値のリスト」などが指定できます。

テーブルを作成するときに`AttributeType`として「N」を指定しましたが、それと同じ指定をしてください。
ちなみに[その記事](https://qiita.com/shuhey/items/cb73812986614af629b3)を書いたときは意味がわかっていませんでした。

#追加してみましょう
ということで、以上を踏まえてテーブルにデータを追加してみます。
データを追加する処理を`PutItem`というメソッドとして切り出してあります。
今回は、このメソッドの中で追加するデータを直接指定していますが、実用性を考えるのであれば追加するデータを引数として受け取るようにすると良いでしょう。

```csharp:Function.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Alexa.NET.Request;
using Alexa.NET.Response;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;


// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace DynamoDBTest
{
    public class Function
    {
        /// <summary>
        /// A simple function that takes a string and does a ToUpper
        /// </summary>
        /// <param name="input"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context)
        {
            //ここにDynamoDBにアクセスするコードを追加していく
            string tableName = "TestTable";//テーブル名
            AmazonDynamoDBClient client = new AmazonDynamoDBClient();//主役。これを介してDynamoDBにアクセスする

            //同名テーブルの存在確認
            if (!IsTableExist(client, tableName))
            {
                //テーブルを作成
                CreateTable(client, tableName);
            }

            PutItem(client, tableName);

            return new SkillResponse
            {
                Version = "1.0",
                Response = new ResponseBody()
            };
        }


        /// <summary>
        /// DynamoDBにテーブルを作成する
        /// </summary>
        /// <param name="client"></param>
        /// <param name="tableName"></param>
        private void CreateTable(IAmazonDynamoDB client, string tableName)
        {
            //リクエストを構築
            var request = new CreateTableRequest
            {
                //テーブルの列情報を設定
                //「ThisIsId」と「ThisIsSomthing」という2つの列を持つテーブルを作る
                AttributeDefinitions = new List<AttributeDefinition>()
                {
                    new AttributeDefinition
                    {
                        AttributeName = "ThisIsId",//カラム名
                        AttributeType = "N"//データのタイプ：N：数値、S：文字列、他にもいくつか。勉強中
                    },
                    new AttributeDefinition
                    {
                        AttributeName = "ThisIsSomething",//カラム名
                        AttributeType = "N"//データのタイプ：N：数値、S：文字列、他にもいくつか。勉強中
                    }
                },
                //勉強中
                KeySchema = new List<KeySchemaElement>
                {
                    new KeySchemaElement
                    {
                        AttributeName = "ThisIsId",
                        KeyType = KeyType.HASH //Partition key
                    },
                    new KeySchemaElement
                    {
                        AttributeName = "ThisIsSomething",
                        KeyType = KeyType.RANGE,//Sort key
                    }
                },
                //勉強中
                ProvisionedThroughput = new ProvisionedThroughput
                {
                    ReadCapacityUnits = 5,
                    WriteCapacityUnits = 5
                },
                //テーブル名
                TableName = tableName
            };

            //テーブル作成リクエストを投げる！
            //ただし、非同期メソッドの返りを待たねければならない。
            //待たないと先にこのLambdaが終了して、DynamoDBのテーブル作成処理を完了せずに終わる。
            //でもメソッドにasyncつけたら、最終的にスキルのレスポンスの型もTask<SkillResponse>にしなきゃいけなくなってだめ。
            //.Wait()メソッドで非同期メソッドを同期メソッドにしちゃえば、返り値も変えなくていいし、テーブル作成完了まで待つことができる。
            //一回完結のサーバー側の処理で非同期でなきゃいけない理由ないしね。
            //client.CreateTableAsync(request).Wait();

            //Waitメソッドではただ非同期メソッドの完了を待つだけでしたが、非同期メソッドの返り値を取得したい場合は、Resultプロパティを使いましょう。
            //Resultプロパティにアクセスすることで、非同期メソッドの完了を待った上で結果を取得することができます。
            //結果を使って何か処理を行いたい場合はこちらが良いのではないでしょうか。
            var result = client.CreateTableAsync(request).Result;
        }


        /// <summary>
        /// 同名のテーブルが存在するかをチェックします。
        /// </summary>
        /// <param name="client"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        private bool IsTableExist(IAmazonDynamoDB client, string tableName)
        {
            //テーブル一覧を取得
            var tableList = client.ListTablesAsync().Result;
            //TableNamesプロパティをチェック
            return tableList.TableNames.Exists(s => s.Equals(tableName));
        }


        /// <summary>
        /// データをテーブルに追加します。
        /// </summary>
        /// <param name="client"></param>
        /// <param name="tableName"></param>
        private void PutItem(IAmazonDynamoDB client, string tableName)
        {
            //リクエストの構築
            var request = new PutItemRequest
            {
                TableName = tableName,//追加先のテーブル名
                //各カラムの値を指定
                Item = new Dictionary<string, AttributeValue>
                {
                    {"ThisIsId",new AttributeValue{N= "2"} },
                    {"ThisIsSomething",new AttributeValue{N="5"} }
                }
            };

            //テーブルに追加
            var result = client.PutItemAsync(request).Result;
        }
    }
}

```

前回と同じようにデプロイしてテストしてみましょう。
AWSコンソールで確認してみると、以下のようにデータが追加されていることが確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/dc40d01b-3e9e-68a1-d447-bf6fab1938d0.png)


#おわりに
テーブルへのデータの追加の流れと基本的な方法について、少し理解が進みました。
しかしこれは単純なデータの追加だけですので、Alexaスキルでデータの保持に使用するにはまだ足りないことばかりです。
が、次はこれをもとに[公式チュートリアル第4回](https://developer.amazon.com/ja/blogs/alexa/post/4144a8ea-7549-4c44-a4bd-e94cb93807ea/chapter4-jp)をC#でやってみようと思います。
その試行錯誤によって更に理解が進むものと思います。