FluentDynamoDB v1.1.0 is now available on NuGet. This is a release I've been working toward for a while, and it focuses on the rough edges that showed up most often in real usage: forgotten key prefixes, stringly-typed computed key parameters, and runtime errors that should have been compile errors.
The full release post with detailed examples is on the FluentDynamoDB website. Here's what changed and why.
Automatic Key Prefix Application
The single most common mistake in v1.0 was forgetting to call Keys.Pk() before a Put. The prefix wouldn't get applied, the item would land in the table with a bare value as its key, and the query that expected the prefix would silently miss it.
In v1.1.0, Put operations automatically apply configured prefixes during serialization. You set the raw value, and the framework prepends the prefix for you:
var order = new Order
{
Pk = orderId, // Automatically becomes "ORDER#12345"
Sk = lineId, // Automatically becomes "LINE#abc"
Total = 99.99m
};
await table.Orders.PutAsync(order);
Existing code that already calls Order.Keys.Pk(value) continues to work. Auto mode detects the prefix is already present and passes through. You can also opt into explicit KeyInputMode.Value (always prepend) or KeyInputMode.Raw (never prepend) per-call or globally.
Typed Overloads for Computed Keys
Computed keys in v1.0 only accepted string parameters. If your key was composed from an enum, a Guid, or a DateTime, you were calling .ToString() everywhere.
v1.1.0 generates typed overloads that match the types of your [Extracted] source properties directly:
// v1.0: manual conversion
var product = await table.Products.GetAsync(category.ToString(), productId.ToString());
// v1.1: typed overloads generated automatically
var product = await table.Products.GetAsync(category, productId);
This covers enum, int, Guid, DateTime, DateOnly, and TimeOnly, with proper AttributeValue construction for each type.
Computed Field Format Specifiers
Computed format strings now support standard .NET format specifiers, evaluated with CultureInfo.InvariantCulture:
[SortKey]
[DynamoDbAttribute("sk")]
[Computed("EventDate", "Category", Format = "{0:yyyy-MM-dd}#{1}")]
public string Sk { get; set; } = string.Empty;
// Produces: "2024-03-15#electronics"
Named Blob Providers and Per-Property Encryption Keys
Entities with multiple blob properties can now route each one to a different storage backend based on the type of content:
var options = new FluentDynamoDbOptions()
.WithBlobStorage(new S3BlobProvider(s3Client, "default-bucket"))
.WithBlobStorage("images", new S3BlobProvider(s3Client, "images-bucket"))
.WithBlobStorage("documents", new S3BlobProvider(s3Client, "docs-bucket"));
Similarly, the [Encrypted] attribute now supports a KeyAlias property so different fields on the same entity can use different KMS keys based on data classification:
[Encrypted(KeyAlias = "pii")]
[DynamoDbAttribute("ssn")]
public string Ssn { get; set; } = string.Empty;
[Encrypted(KeyAlias = "financial")]
[DynamoDbAttribute("accountNumber")]
public string AccountNumber { get; set; } = string.Empty;
Async KMS Key Resolver (Breaking Change)
The IKmsKeyResolver interface moved from synchronous to asynchronous. This was the only blocking call in an otherwise fully-async encryption pipeline, and it needed to change to support key resolution that actually does I/O: database lookups, secrets managers, external APIs.
// Before
public interface IKmsKeyResolver
{
string ResolveKeyId(string? contextId);
}
// After
public interface IKmsKeyResolver
{
Task<string> ResolveKeyIdAsync(
string? contextId,
string? keyAlias = null,
CancellationToken cancellationToken = default);
}
See the encryption documentation for details on the new interface.
Compile-Time Safety Improvements
Several categories of runtime errors are now compile errors:
- Update model safety: Key properties and computed fields are excluded from generated update models. Attempting to set a key in an update expression fails at compile time.
- Constant key detection: Keys that return a fixed value (via expression-body or read-only auto-property syntax) are detected automatically, simplifying the generated Keys class and accessor methods.
- Schema versioning: A new
[FluentDynamoDbSchemaVersion]assembly attribute decouples generated code shape from the NuGet package version, so you can migrate at your own pace when the generated output changes.
Auto-Derived Discriminator Patterns
This one was a big deal internally. Multi-entity tables no longer require manually specifying DiscriminatorPattern. The source generator derives it from key prefix and computed format configurations.
It sounds simple, but getting it right across our own edge cases took multiple development cycles. Overlapping prefixes, compound key discrimination, entities that share the same sort key prefix but differ by partition key. The generator now resolves overlapping patterns automatically using specificity scoring with exclusion guards, and falls back to compound key checks when specificity alone isn't enough.
New diagnostics (FDDB100-FDDB104) catch prefix conflicts, discriminator contradictions, and overlapping patterns at compile time so you don't hit them at runtime.
In total, this release adds 15 new compile-time diagnostics. All diagnostic codes now include helpLinkUri linking to documentation at fluentdynamodb.dev/diagnostics.
Installing
dotnet add package Oproto.FluentDynamoDb --version 1.1.0
For the complete release notes with full before/after examples for every feature, see the official v1.1.0 announcement on fluentdynamodb.dev.