Hello, everyone! This week, I was learning AWS Lambda Function, especially using .NET Container. I will continue my post and extends more use cases. I will connect the previous Lambda Function to Amazon DynamoDB.
Start Project
Please continue the project from this commit. In short, you may use this project directly to explore. If you want to check what's the changes, please visit here.
Update our Lambda Functions Code
Install Dependencies to Existing Project
You will need install Amazon DynamoDB dependencies before you use it. Please use this command: dotnet add src/SimpleAPI/ package AWSSDK.DynamoDBv2 --version 3.7.3.57
. I use version 3.7.3.57
.
Add Model
Please add this model file to src/SimpleAPI/Models/Note.cs
. We will use a simple model in this case just for proof of the concept.
namespace SimpleAPI.Models;
using Amazon.DynamoDBv2.DataModel;
[DynamoDBTable("Notes")]
public class Note
{
[DynamoDBHashKey]
public Guid Id {get; set;}
public String Message {get; set;}
}
Add Notes Controller
We will need add new controller to handle the API.
using Microsoft.AspNetCore.Mvc;
using Amazon.DynamoDBv2.DataModel;
using SimpleAPI.Models;
using Amazon.DynamoDBv2;
namespace SimpleAPI.Controllers;
[Route("api/[controller]")]
public class NotesController : ControllerBase
{
private readonly AmazonDynamoDBClient _dynamoDBClient;
private readonly DynamoDBContext _dbContext;
public NotesController()
{
AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig();
_dynamoDBClient = new AmazonDynamoDBClient(clientConfig);
_dbContext = new DynamoDBContext(_dynamoDBClient);
}
[HttpGet]
public async Task<IEnumerable<Note>> Get()
{
var notes = _dbContext.ScanAsync<Note>(new List<ScanCondition>());
var results = await notes.GetRemainingAsync();
return results;
}
[HttpGet("{id}")]
public async Task<Note?> Get(Guid id)
{
var notes = _dbContext.QueryAsync<Note>(id);
var results = await notes.GetRemainingAsync();
return results.FirstOrDefault();
}
[HttpPost]
public async Task<Note> Post([FromBody] Note value)
{
var batch = _dbContext.CreateBatchWrite<Note>();
value.Id = Guid.NewGuid();
batch.AddPutItem(value);
await batch.ExecuteAsync();
return value;
}
[HttpPut("{id}")]
public async Task<IResult> Put(Guid id, [FromBody] Note value)
{
var notes = _dbContext.QueryAsync<Note>(id);
var results = await notes.GetRemainingAsync();
var first = results.FirstOrDefault();
if (first == null)
{
return Results.NotFound();
}
first.Message = value.Message;
var batch = _dbContext.CreateBatchWrite<Note>();
batch.AddPutItem(first);
await batch.ExecuteAsync();
return Results.Ok(first);
}
[HttpDelete("{id}")]
public async Task<IResult> Delete(Guid id)
{
var notes = _dbContext.QueryAsync<Note>(id);
var results = await notes.GetRemainingAsync();
var first = results.FirstOrDefault(); if (first == null)
{
return Results.NotFound();
}
var batch = _dbContext.CreateBatchWrite<Note>();
batch.AddDeleteItem(first);
await batch.ExecuteAsync();
return Results.Ok();
}
}
Update our Terraform Code
- You will need to add this permission to the execution role of the lambda:
inline_policy {
name = "lambda-custom"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
Resource = "*"
}, {
Effect = "Allow",
Action = [
"dynamodb:DescribeTable",
"dynamodb:GetRecords",
"dynamodb:GetShardIterator",
"dynamodb:ListTables",
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:BatchWriteItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem"
]
Resource = ["*"]
}] })
}
- I also extend the timeout to make sure it's not terminated when I call the API.
tracing_config {
mode = "Active"
}
timeout = 60
- Please make sure your
aws_lambda_function_url
already allows all methods.
allow_methods = ["*"]
- Add Amazon DynamoDB resource.
resource "aws_dynamodb_table" "lambda_container_demo_dev" {
name = "Notes"
billing_mode = "PROVISIONED"
read_capacity = 20
write_capacity = 20
hash_key = "Id"
attribute {
name = "Id"
type = "S"
}
attribute {
name = "Message"
type = "S"
}
global_secondary_index {
name = "NoteMessageIndex"
hash_key = "Message"
write_capacity = 10
read_capacity = 10
projection_type = "INCLUDE"
non_key_attributes = ["Id"]
}
ttl {
attribute_name = "TimeToExist"
enabled = true
}
tags = {
Name = "dynamodb-table-1"
Environment = "dev"
}
}
Done!
bervProject / lambda-sharp
Lambda use C# (.NET) Docker Image
Lambda Sharp Demo
Demo for Lambda Containerized .NET
LICENSE
MIT
Time to deploy your code to Amazon ECR and run terraform apply
so your resources are provisioned.
You may look at these screenshots for my testing the CRUD of Notes Functions.
- Get All Notes
- Create a Note
- Update a Note
- Get a Note by Id
- Delete
Thank you!
So, what do you think? It's quite simple, right? Let's share what's in your mind!
Top comments (0)