C# .NET Core implementation of the repository pattern using DynamoDB as data store using single table and hierarchical data modelling approach overloading the partition and sort key as well secondary index.
This implementation aims to solve the most common data persistence use cases ranging from independent entities to more complex data models.
Key features:
- Ready to use CRUD operations.
- Ready to use batch operations.
- Generic design for flexibility of data types.
- One to many relationship.
- Many to many relationships
- Define your entity as a POCO, no interface or annotations required.
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
- Inherit from
SimpleRepository<TKey, TEntity>
abstract class.
public class PersonRepository : SimpleRepository<int, Person>
{
}
- Define partition key prefix and sort key prefix in constructor.
public PersonRepository(string tableName, string serviceUrl = null) : base(tableName, serviceUrl)
{
PKPrefix = "PERSON";
SKPrefix = "METADATA";
}
- Override
TKey GetEntityKey(TEntity item)
abstract method to return the entity identifier.
protected override int GetEntityKey(Person item)
{
return item.Id;
}
- Override
DynamoDBItem ToDynamoDb(TEntity item)
abstract method to map the entity object to a DynamoDB attribute dictionary.
protected override DynamoDBItem ToDynamoDb(Person item)
{
var dbItem = new DynamoDBItem();
dbItem.AddNumber("Id", item.Id);
dbItem.AddString("Name", item.Name);
dbItem.AddString("Email", item.Email);
dbItem.AddNumber("Age", item.Age);
return dbItem;
}
- Override
TEntity FromDynamoDb(DynamoDBItem item)
abstract method to map the DynamoDB attribute dictionary to an entity object.
protected override Person FromDynamoDb(DynamoDBItem item)
{
var result = new Person();
result.Id = item.GetInt32("Id");
result.Name = item.GetString("Name");
result.Email = item.GetString("Email");
result.Age = item.GetInt32("Age");
return result;
}
- Use the available methods either directly or through the interface.
public static async Task TestCRUD_PersonRepository()
{
// Create a new PersonRepository
ISimpleRepository<int, Person> repo = new PersonRepository(_tableName);
// Prepare a Person instance
var p1 = new Person
{
Id = 1,
Name = "personA",
Email = "[email protected]",
Age = 35
};
Console.WriteLine("* Adding Person 1");
// Add a new person
await repo.Add(p1);
Console.WriteLine("* Getting the list");
// Get the full list
var list = await repo.GetList();
foreach (var item in list)
{
Console.WriteLine(JsonSerializer.Serialize(item));
}
Console.ReadKey();
Console.WriteLine("* Getting Person 1");
// Get an individual Person by its Id
var found1 = await repo.Get(p1.Id);
Console.WriteLine(JsonSerializer.Serialize(found1));
Console.WriteLine("* Deleting Person 1");
// Delete an individual Person by its Id
await repo.Delete(p1.Id);
}