Quick Start
Get up and running with FluentDynamoDB in minutes.
Define an Entity
Create a C# class that maps to your DynamoDB table. The class must be partial to allow the source generator to add mapping code.
using Oproto.FluentDynamoDb.Attributes;
// The class MUST be partial - the source generator adds mapping code
[DynamoDbTable("users")]
public partial class User
{
// PartitionKey marks this property as the table's partition key
// DynamoDbAttribute maps the property to the DynamoDB attribute name "pk"
[PartitionKey]
[DynamoDbAttribute("pk")]
public string UserId { get; set; } = string.Empty;
// Optional: SortKey for composite primary keys
// [SortKey]
// [DynamoDbAttribute("sk")]
// public string SortKey { get; set; } = string.Empty;
// Map each property to its DynamoDB attribute name
[DynamoDbAttribute("email")]
public string Email { get; set; } = string.Empty;
[DynamoDbAttribute("name")]
public string Name { get; set; } = string.Empty;
[DynamoDbAttribute("status")]
public string Status { get; set; } = "active";
[DynamoDbAttribute("created_at")]
public DateTime CreatedAt { get; set; }
}
Key Points:
partialclass is required for source generation- Exactly one
[PartitionKey]property is required [DynamoDbAttribute]maps properties to DynamoDB attribute names[SortKey]is optional for tables with composite keys
Create a Table Instance
The source generator creates a typed table class for your entity. Instantiate it with a DynamoDB client.
using Amazon.DynamoDBv2;
var client = new AmazonDynamoDBClient();
// Basic instantiation - uses default settings
var table = new UsersTable(client, "users");
With Configuration Options
Use FluentDynamoDbOptions to configure logging and other features:
using Microsoft.Extensions.Logging;
using Oproto.FluentDynamoDb;
using Oproto.FluentDynamoDb.Logging;
// Create options with logging enabled
var options = new FluentDynamoDbOptions()
.WithLogger(loggerFactory.ToDynamoDbLogger<UsersTable>());
var table = new UsersTable(client, "users", options);
Basic Operations
The library provides express-route methods for simple operations. Use the entity accessor (table.Users) for cleaner, type-safe code.
Create (Put)
var user = new User
{
UserId = "user123",
Email = "user@example.com",
Name = "John Doe",
CreatedAt = DateTime.UtcNow
};
// Express-route - simplest approach
await table.Users.PutAsync(user);
Read (Get)
// Express-route - returns the entity directly
var user = await table.Users.GetAsync("user123");
if (user != null)
{
Console.WriteLine($"Found user: {user.Name}");
}
Update
Use lambda expressions for type-safe, readable updates:
// Lambda expression - type-safe with IntelliSense
await table.Users.Update("user123")
.Set(x => new { Name = "Jane Doe" })
.UpdateAsync();
Delete
// Express-route delete
await table.Users.DeleteAsync("user123");
Query Data
Query items using lambda expressions for type-safe queries:
// Lambda expression query - type-safe with IntelliSense
var users = await table.Users.Query()
.Where(x => x.UserId == "user123")
.ToListAsync();
foreach (var user in users)
{
Console.WriteLine($"User: {user.Name}, Email: {user.Email}");
}
Conditional Query Example
Add conditions to filter results:
// Query with additional conditions
var activeUsers = await table.Users.Query()
.Where(x => x.UserId == "user123" && x.Status == "active")
.ToListAsync();
Next Steps
- Learn about Core Concepts - Entity design patterns and attributes
- Explore Querying - Advanced query techniques
- Set up Source Generation - Understand generated code