AWS DynamoDB, S3, SQS を .NET Core で使うコードスニペット集

 AWS で比較的使われることが多い DynamoDB, S3, SQS を .NET Core & C# で使う際のコードスニペットをまとめました。

- [Amazon DynamoDB](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#amazon-dynamodb)
  - [Scan (全件取得)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#scan-%E5%85%A8%E4%BB%B6%E5%8F%96%E5%BE%97)
  - [Query (検索取得)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#query-%E6%A4%9C%E7%B4%A2%E5%8F%96%E5%BE%97)
  - [Query (GSIの検索取得)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#query-gsi%E3%81%AE%E6%A4%9C%E7%B4%A2%E5%8F%96%E5%BE%97)
  - [GetItem (要素の取得)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#getitem-%E8%A6%81%E7%B4%A0%E3%81%AE%E5%8F%96%E5%BE%97)
  - [BatchGetItem 処理 (複数要素をまとめて取得)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#batchgetitem-%E5%87%A6%E7%90%86-%E8%A4%87%E6%95%B0%E8%A6%81%E7%B4%A0%E3%82%92%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E5%8F%96%E5%BE%97)
  - [UpdateItem 処理 (追加・更新処理)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#updateitem-%E5%87%A6%E7%90%86-%E8%BF%BD%E5%8A%A0%E6%9B%B4%E6%96%B0%E5%87%A6%E7%90%86)
  - [DeleteItem 処理 (削除処理)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#deleteitem-%E5%87%A6%E7%90%86-%E5%89%8A%E9%99%A4%E5%87%A6%E7%90%86)
  - [BatchWriteItem 処理 (複数要素をまとめて更新)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#batchwriteitem-%E5%87%A6%E7%90%86-%E8%A4%87%E6%95%B0%E8%A6%81%E7%B4%A0%E3%82%92%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E6%9B%B4%E6%96%B0)
  - [TransactWriteItems (トランザクションでの更新処理)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#transactwriteitems-%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A7%E3%81%AE%E6%9B%B4%E6%96%B0%E5%87%A6%E7%90%86)
- [Amazon S3](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#amazon-s3)
  - [アップロード処理](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E5%87%A6%E7%90%86)
  - [ダウンロード処理](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E5%87%A6%E7%90%86)
  - [署名付きURLの発行](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#%E7%BD%B2%E5%90%8D%E4%BB%98%E3%81%8Durl%E3%81%AE%E7%99%BA%E8%A1%8C)
- [Amazon SQS](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#amazon-sqs)
  - [SendMessage 処理 (エンキュー)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#sendmessage-%E5%87%A6%E7%90%86-%E3%82%A8%E3%83%B3%E3%82%AD%E3%83%A5%E3%83%BC)
  - [SendMessageBatch 処理 (まとめてのエンキュー)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#sendmessagebatch-%E5%87%A6%E7%90%86-%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E3%81%AE%E3%82%A8%E3%83%B3%E3%82%AD%E3%83%A5%E3%83%BC)
  - [ReceiveMessage 処理 (デキュー)](https://qiita.com/mahiya/items/8a1e45bc370d4212ad37#receivemessage-%E5%87%A6%E7%90%86-%E3%83%87%E3%82%AD%E3%83%A5%E3%83%BC)

# Amazon DynamoDB

DynamoDBに関するコードスニペットは、[AWSSDK.DynamoDBv2パッケージ](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/)と、以下通りの名前空間の参照とSampleTableItemクラスの定義を使用することを前提としています。

```cs
// dotnet add package AWSSDK.DynamoDBv2
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;

[DynamoDBTable("sample-table")]
class SampleTableItem
{
    [DynamoDBHashKey("pk")]
    public int PartitionKey { get; set; }

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

    [DynamoDBProperty("prop")]
    public string Property { get; set; }
}
```

## Scan (全件取得)

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


## Query (検索取得)

### 指定したPartitionKeyの項目をすべて取得

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
var partitionKey = 0;
var items = await context.QueryAsync<SampleTableItem>(partitionKey).GetRemainingAsync();
```

### 指定したPartitionKeyとSortKeyでの範囲検索

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
// PartitionKeyの値が0で、SortKeyがSampleから始まるあるすべてのItemを取得する
var partitionKey = 0;
var sortKeys = new[] { "Sample" };
var items = await context.QueryAsync<SampleTableItem>(partitionKey, QueryOperator.BeginsWith, sortKeys).GetRemainingAsync();
```


## Query (GSIの検索取得)

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
const string gsiPartitionKey = "SampleSortKey";
const string indexName = "SampleIndex";
var filter = new QueryFilter("sk", QueryOperator.Equal, gsiPartitionKey);
var config = new QueryOperationConfig
{
    Filter = filter,
    IndexName = indexName
};
var items = await context.QueryAsync<SampleTableItem>(config).GetRemainingAsync();
```

> GSI: Global Secondary Index


## GetItem (要素の取得)

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
const int partitionKey = 0;
const string sortKey = "SampleSortKey";
var item = await context.LoadAsync<SampleTableItem>(partitionKey, sortKey);
```


## BatchGetItem 処理 (複数要素をまとめて取得)

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
var batch = context.CreateBatchGet<SampleTableItem>();
batch.AddKey(0, "SampleSortKey1");
batch.AddKey(0, "SampleSortKey2");
await batch.ExecuteAsync();
var items = batch.Results;
```


## UpdateItem 処理 (追加・更新処理)

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
var item = new SampleTableItem
{
    PartitionKey = 0,
    SortKey = "SampleSortKey",
    Property = "Value"
};
await context.SaveAsync(item);
```


## DeleteItem 処理 (削除処理)

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
const int partitionKey = 0;
const string sortKey = "SampleSortKey";
await context.DeleteAsync<SampleTableItem>(partitionKey, sortKey);
```


## BatchWriteItem 処理 (複数要素をまとめて更新)

```cs
var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
var batch = context.CreateBatchWrite<SampleTableItem>();
var items = System.Linq.Enumerable.Range(0, 25).Select(i => new SampleTableItem
{
    PartitionKey = 0,
    SortKey = $"SampleSortKey{i}",
    Property = $"Value{i}"
});
batch.AddPutItems(items);
await batch.ExecuteAsync();
```


## TransactWriteItems (トランザクションでの更新処理)

```cs
var client = new AmazonDynamoDBClient();
var request = new TransactWriteItemsRequest();
request.TransactItems = new List<TransactWriteItem>();
request.TransactItems.Add(new TransactWriteItem
{
    Put = new Put
    {
        TableName = "sample-table",
        Item = new Dictionary<string, AttributeValue>
        {
            { "pk", new AttributeValue { N = "0" } },
            { "sk", new AttributeValue { S = "SampleSortKey1" } },
            { "prop", new AttributeValue { S = "Value" } }
        }
    }
});
request.TransactItems.Add(new TransactWriteItem
{
    Delete = new Delete
    {
        TableName = "sample-table",
        Key = new Dictionary<string, AttributeValue>
        {
            { "pk", new AttributeValue { N = "0" } },
            { "sk", new AttributeValue { S = "SampleSortKey2" } }
        }
    }
});
await client.TransactWriteItemsAsync(request);
```

> Amazon DynamoDB トランザクション: 仕組み
> https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/transaction-apis.html

# Amazon S3

S3に関するスニペットは[AWSSDK.S3パッケージ](https://www.nuget.org/packages/AWSSDK.S3/)と以下の名前空間を使用します。

```cs
// dotnet add package AWSSDK.S3
using Amazon.S3;
using Amazon.S3.Transfer;
```

## アップロード処理

### アップロードするファイルのパスを指定してアップロード

```cs
var client = new AmazonS3Client();
var transfer = new TransferUtility(client);

const string bucketName = "sample-bucket";
const string key = "sample-uploaded-file.txt";
const string uploadFilePath = "sample-uploaded-file.txt";
await transfer.UploadAsync(uploadFilePath, bucketName, key);
```

### アップロードするデータのバイナリを指定してアップロード

```cs
var client = new AmazonS3Client();
var transfer = new TransferUtility(client);

const string bucketName = "sample-bucket";
const string key = "sample-uploaded-file.txt";
var bytes = System.Text.Encoding.UTF8.GetBytes("Hello S3 !");
using (var stream = new MemoryStream(bytes))
{
    await transfer.UploadAsync(stream, bucketName, key);
}
```

## ダウンロード処理

### ダウンロードしてファイルとして保存する

```cs
var client = new AmazonS3Client();
var transfer = new TransferUtility(client);

const string bucketName = "sample-bucket";
const string key = "sample-uploaded-file.txt";
const string downloadFilePath = "s3_sample_download.txt";
await transfer.DownloadAsync(downloadFilePath, bucketName, key);
```

### ダウンロードしたファイルをメモリ上で扱う

```cs
var client = new AmazonS3Client();

const string bucketName = "sample-bucket";
const string key = "sample-uploaded-file.txt";
var s3Object = await client.GetObjectAsync(bucketName, key);
using (var stream = new StreamReader(s3Object.ResponseStream))
{
    var text = await stream.ReadToEndAsync();
}
```

## 署名付きURLの発行

```cs
const string bucketName = "sample-bucket";
const string key = "sample-uploaded-file.txt";

var client = new AmazonS3Client();
var request = new Amazon.S3.Model.GetPreSignedUrlRequest
{
    BucketName = bucketName,
    Key = key,
    Verb = HttpVerb.GET,
    Expires = DateTime.UtcNow.AddMinutes(1)
};
var presignedUrl = client.GetPreSignedURL(request);
```

> 署名付き URL を使用したオブジェクトのアップロード
> https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/PresignedUrlUploadObject.html


# Amazon SQS

S3に関するスニペットは[AWSSDK.S3パッケージ](https://www.nuget.org/packages/AWSSDK.S3/)と以下の名前空間を使用します。

```cs
// dotnet add package AWSSDK.SQS
using Amazon.SQS;
using Amazon.SQS.Model;
```

## SendMessage 処理 (エンキュー)

```cs
var client = new AmazonSQSClient();
const string queueUrl = "https://sqs.region-name.amazonaws.com/0000000000/your-queue-name";
await client.SendMessageAsync(queueUrl, "Hello SQS !");
```

## SendMessageBatch 処理 (まとめてのエンキュー)

```cs
var client = new AmazonSQSClient();
const string queueUrl = "https://sqs.region-name.amazonaws.com/0000000000/your-queue-name";
var messages = System.Linq.Enumerable.Range(0, 5).Select(i => new SendMessageBatchRequestEntry
{
    Id = i.ToString(),
    MessageBody = "Hello SQS !! - " + i,
}).ToList();
await client.SendMessageBatchAsync(queueUrl, messages);
```

## ReceiveMessage 処理 (デキュー)

```cs
var client = new AmazonSQSClient();
const string queueUrl = "https://sqs.region-name.amazonaws.com/0000000000/your-queue-name";
var receiveMessageRequest = new ReceiveMessageRequest
{
    QueueUrl = queueUrl,
    MaxNumberOfMessages = 10
};
var resp = await client.ReceiveMessageAsync(receiveMessageRequest);
var messages = resp.Messages;
```