-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
DynamoDbLite is an in-process IAmazonDynamoDB backed by SQLite — use it as a drop-in replacement for DynamoDB in tests, local development, and offline-capable apps. This page walks through installation, DI registration, direct construction, and a minimal working example.
Built against AWSSDK.DynamoDBv2 v4 on .NET 10. See the AWS DynamoDB Developer Guide for DynamoDB concepts.
- .NET 10 SDK
- Source reference — NuGet packages are not yet published
Add a project reference to DynamoDbLite:
<ProjectReference Include="..\DynamoDbLite\src\DynamoDbLite\DynamoDbLite.csproj" />The DI extension (AddDynamoDbLite) ships in the same project — no separate package. Once published, the package is available on NuGet as MSL.DynamoDbLite.
using DynamoDbLite;
builder.Services.AddDynamoDbLite(o =>
o.WithConnectionString("Data Source=myapp.db"));AddDynamoDbLite registers IAmazonDynamoDB as a singleton via TryAddSingleton. See DI and Configuration for the validation surface, exception types, eager-validation behavior, and notes on IConfiguration binding.
using DynamoDbLite;
// File-based (persistent)
using var fileClient = new DynamoDbClient(new DynamoDbLiteOptions(
"Data Source=myapp.db"));
// In-memory
using var memoryClient = new DynamoDbClient(new DynamoDbLiteOptions(
$"Data Source=app_{Guid.NewGuid():N};Mode=Memory;Cache=Shared"));DynamoDbLiteOptions.ConnectionString is required — there is no default. DynamoDbClient implements IDisposable but not IAsyncDisposable — use using var, not await using. Or let the DI container manage its lifetime.
| Mode | Connection String | Use Case |
|---|---|---|
| In-Memory | Data Source=<unique-name>;Mode=Memory;Cache=Shared |
Unit tests, development |
| File-Based | Data Source=myapp.db |
Persistent storage, mobile apps |
The mode is auto-detected from the connection string: :memory: or Mode=Memory selects an in-memory store; otherwise a file-based store is created. File-based stores opt into WAL (write-ahead logging) mode by setting UseWriteAheadLog = true on DynamoDbLiteOptions (or calling WithWriteAheadLog() on the builder). WAL is off by default; see DI and Configuration for the contract.
The Data Source name keys SQLite's shared cache. Two clients in the same process with the same name share one in-memory database — useful when intentional, hazardous when not. For test isolation, suffix the name with a unique value:
$"Data Source=app_{Guid.NewGuid():N};Mode=Memory;Cache=Shared"Cache=Shared is required for in-memory mode — the library opens a fresh connection per operation and would otherwise see an empty database on every call.
Because each operation runs on its own connection, concurrent calls reach the shared database in parallel. Writes need no application-level lock: when two writers collide, the second retries until the first commits — Microsoft.Data.Sqlite drives that retry from the connection's CommandTimeout (default 30 s).
busy_timeout is inert for in-memory stores. Shared-cache write conflicts raise SQLITE_LOCKED_SHAREDCACHE, which SQLite's busy handler does not service, so the pragma changes nothing — the command-timeout retry is what serializes writers. busy_timeout is the contention knob for file-backed stores, where conflicts surface as SQLITE_BUSY. See Concurrency for the full model and WithPragma for the pragma surface.
A complete in-memory registration. The busy_timeout pragma is inert for an in-memory store but harmless, and keeps the configuration correct if the same code later targets a file:
using DynamoDbLite;
builder.Services.AddDynamoDbLite(o => o
.WithConnectionString($"Data Source=app_{Guid.NewGuid():N};Mode=Memory;Cache=Shared")
.WithPragma("busy_timeout", "5000"));using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using DynamoDbLite;
using var client = new DynamoDbClient(new DynamoDbLiteOptions(
$"Data Source=app_{Guid.NewGuid():N};Mode=Memory;Cache=Shared"));
// Create a table
await client.CreateTableAsync(new CreateTableRequest
{
TableName = "Users",
KeySchema =
[
new KeySchemaElement { AttributeName = "UserId", KeyType = KeyType.HASH }
],
AttributeDefinitions =
[
new AttributeDefinition { AttributeName = "UserId", AttributeType = ScalarAttributeType.S }
],
ProvisionedThroughput = new ProvisionedThroughput
{
// Accepted for API compatibility but not enforced — DynamoDbLite has no capacity limits.
ReadCapacityUnits = 5,
WriteCapacityUnits = 5
}
});
// Put an item
await client.PutItemAsync(new PutItemRequest
{
TableName = "Users",
Item = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-123" },
["Name"] = new() { S = "Alice" },
["Age"] = new() { N = "30" }
}
});
// Get the item
var response = await client.GetItemAsync(new GetItemRequest
{
TableName = "Users",
Key = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-123" }
}
});
Console.WriteLine(response.Item["Name"].S); // "Alice"DynamoDbLiteOptions is a positional record with one required parameter and one optional flag:
| Property | Type | Description |
|---|---|---|
ConnectionString |
string |
SQLite connection string. Required — see Storage Modes for the in-memory and file-based forms. |
UseWriteAheadLog |
bool |
Defaults to false. Set to true to enable SQLite WAL on file-backed stores. No effect on in-memory stores. See DI and Configuration for the full contract. |
The connection string follows Microsoft.Data.Sqlite connection string format. The library applies ForeignKeys=true when you leave it unset and otherwise uses the string as written — Mode and Pooling are preserved. Honoring Mode is what lets Mode=Memory select an in-memory store instead of being rewritten to a file.
- Table Operations — creating and managing tables
- Item Operations — reading and writing data
- Query and Scan — filtering and scanning items
- Secondary Indexes — adding GSIs and LSIs
Repo · NuGet · API Parity
Getting started
Reference
- Table Operations
- Item Operations
- Query and Scan
- Batch Operations
- Transactions
- Secondary Indexes
- TTL
- Tags and Admin
- DI and Configuration
- Concurrency
- Performance
- API Parity
- FAQ
Recipes
- DynamoDBContext for tests
- xUnit per-test isolation
- ASP.NET Core integration test fixture
- Migrating tests off DynamoDB Local
Internals