今回はDynamoDBへのCRUD操作を、C#で書いて、Lambdaで動かしてみたいと思います。
テーブルの作成
まずはAWS ConsoleからDynamoDBへテーブルを予め作成します。
- テーブル名を"Todos"とします。
- パーティションキーを"Id"、ソートキーを"Due"とします。
エンティティクラスの作成
AWS Lambdaプロジェクトを作成し、今回はDynamoDBTable属性を付与したエンティティクラスを使います。
- AWS Lambdaプロジェクトの作成とデプロイは下記の投稿に詳しく記載されています。
qiita.com
- DynamoDBTable属性が付与することでTodoEntityクラスがテーブル("Todos")へマッピングされます。
using System.Collections.Generic;
using Amazon.DynamoDBv2.DataModel;
namespace AWSLambda
{
[DynamoDBTable("Todos")]
public class TodoEntity
{
[DynamoDBHashKey]
public string Id { get; set; }
[DynamoDBRangeKey]
public string Due { get; set; }
[DynamoDBProperty("Done")]
public bool? DoneFlag { get; set; }
public List<string> Contents { get; set; }
[DynamoDBIgnore]
public string Operation { get; set; }
}
}
Lambdaの作成
それではLambdaを作成します。
- TodosテーブルへマッピングされたTodoEntityオブジェクトを介すことで、DynamoDBへ接続されたDynamoDBContextを使って読み書きします。
- TodoEntityクラスを引数として、Operationの値によってInsert/Select/Update/Deleteの処理を分岐しています。
- いずれの処理もパーティションキーとソートキーの指定が必要です。
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Lambda.Core;
using Newtonsoft.Json;
namespace AWSLambda
{
public class DynamoDbOperationFunction
{
private static readonly AmazonDynamoDBClient Client = new AmazonDynamoDBClient(RegionEndpoint.USWest2);
[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
public void DynamoDbOperationHandler(TodoEntity entity, ILambdaContext context)
{
context.Logger.LogLine(JsonConvert.SerializeObject(entity));
using (var dbContext = new DynamoDBContext(Client))
{
switch (entity.Operation)
{
case "Insert":
var insertTask = dbContext.SaveAsync(entity);
insertTask.Wait();
break;
case "Select":
var selectTask = dbContext.LoadAsync<TodoEntity>(hashKey: entity.Id, rangeKey: entity.Due);
selectTask.Wait();
context.Logger.LogLine(JsonConvert.SerializeObject(selectTask.Result));
break;
case "Update":
var updateTask1 = dbContext.LoadAsync<TodoEntity>(hashKey: entity.Id, rangeKey: entity.Due);
updateTask1.Wait();
var updatedEntity = updateTask1.Result;
updatedEntity.Contents = entity.Contents ?? updatedEntity.Contents;
updatedEntity.DoneFlag = entity.DoneFlag ?? updatedEntity.DoneFlag;
var updateTask2 = dbContext.SaveAsync(entity);
updateTask2.Wait();
break;
case "Delete":
var deleteTask = dbContext.DeleteAsync<TodoEntity>(hashKey: entity.Id, rangeKey: entity.Due);
deleteTask.Wait();
break;
}
}
}
}
}
動作確認
それではAWS Explorerからデプロイして動作確認します。
Insertでは以下のような引数用のJSONを作成し、
{
"Id": "001",
"Due": "2017-01-10T10:00:00",
"DoneFlag": false,
"Contents": [
"abcde",
"12345"
],
"Operation": "Insert"
}
AWS Explorerから実行してみます。
そしてAWS ConsoleからDynamoDBのTodosテーブルを開くと、Idが"001"のレコードが作成されていることがわかるかと思います。
- Contentsに複数項目、またOperationが無いことも確認してください。
同じようにSelectも以下のような引数用のJSONを作成し、
{
"Id": "001",
"Due": "2017-01-10T10:00:00",
"Operation": "Select"
}
AWS Explorerから実行すると参照できていることも確認できるかと思います。
UpdateではDoneFlagとContentsを変更した引数を渡しており、
{
"Id": "001",
"Due": "2017-01-10T10:00:00",
"DoneFlag": true,
"Contents": [
"ABCDE",
"54321"
],
"Operation": "Update"
}
それぞれ更新されていることが確認できます。
Deleteもパーティションキーとソートキーを渡すだけです。
{
"Id": "001",
"Due": "2017-01-10T10:00:00",
"Operation": "Delete"
}
まとめ
今回はDynamoDBTable属性とDynamoDBContextを使ってDynamoDBを操作しましたが、ScanやQuery、BatchWrite、BatchGetなども提供されています。
これ以外にもドキュメントモデルや低レベルAPIを使って操作する方法もありますので、今後紹介できればと思います。