Changelog
All notable user-facing changes to FluentDynamoDB are documented here. For internal implementation details, see the repository changelog.
v1.1.0
New Features
- Automatic key prefix application on Put — The source generator now automatically applies configured key prefixes during Put serialization, eliminating the need to manually call
Entity.Keys.Pk(value)before every Put. Controlled via the newKeyInputModeenum (Auto,Value,Raw) with configurable defaults throughFluentDynamoDbOptions.UseKeyInputMode()and per-operation overrides via.WithKeyMode(). - Typed parameter convenience overloads for computed keys — Generated Get, Delete, Update, and ConditionCheck methods now accept individual source property components as typed parameters (e.g.,
table.Events.Get(2024, 12, 25, "EVT#christmas")), supporting non-string types likeint,enum,Guid,DateTime,DateOnly, andTimeOnly. - Computed field format specifiers — Source property
[DynamoDbAttribute(Format = "...")]values are automatically injected into computed format string placeholders that lack an explicit format specifier, eliminating redundant format declarations. - Named blob providers — Register multiple blob storage providers by name with
.WithBlobStorage("name", provider)and route individual properties to specific providers using[BlobStorage(Provider = "name")]. - Per-property encryption key aliases — Use
[Encrypted(KeyAlias = "...")]to route different encrypted properties to different KMS keys.DefaultKmsKeyResolveraccepts a newaliasKeyMapparameter for alias-to-key-ARN mapping. - Auto-derived discriminator patterns — The source generator automatically derives discriminator patterns from key prefix and format configurations, eliminating manual
DiscriminatorPatternspecification in most single-table designs. - Compound key discrimination (FDDB104) — The source generator now automatically resolves same-score discriminator overlaps between entities on the same table by inspecting cross-key patterns. When two entities share an identical discriminator pattern on one key (e.g., both have
CAP#*on the sort key), the generator checks whether their partition key patterns differ and promotes to a compound discriminator check, suppressing FDDB102/DISC004. - Internal-segment compound discrimination — Extended compound key discrimination to resolve same-prefix entity pairs where one entity's Complex pattern contains a distinguishing internal segment (e.g.,
TENANT#*#ROLE#*vsTENANT#*). Uses positionalIndexOf-based constraints for accurate disambiguation. - Constant key detection — The source generator now detects key properties returning fixed compile-time string values via expression-body (
=>) or read-only auto-property syntax. Constant keys automatically simplify the Keys class, convenience methods, serialization/deserialization, and auto-derive discriminator patterns without manual configuration. - Schema versioning — Declare
[assembly: FluentDynamoDbSchemaVersion(1, 0)]to control source generator output shape upgrades independently of NuGet package versions. New diagnostics FDDB110–FDDB116 enforce the versioning contract. - Update model compile-time safety — Non-updatable properties (partition keys, sort keys, key-based computed fields) are excluded from generated update model classes, converting runtime errors into compile-time errors. Source-property-based updates for non-key computed fields trigger automatic recomputation.
- Unified Keys class API — All key construction now flows through
Pk(...)andSk(...)methods, handling prefix-based, computed, and constant key patterns uniformly.
Breaking Changes
IKmsKeyResolveris now async —ResolveKeyId(string? contextId)is replaced byResolveKeyIdAsync(string? contextId, string? keyAlias, CancellationToken)returningTask<string>. All custom implementations must be updated.DefaultKmsKeyResolverconstructor updated — The existingcontextKeyMapparameter is now named explicitly, and a new optionalaliasKeyMapparameter is available for per-alias key resolution.IBlobStorageProviderparameter overloads removed — All terminal method overloads accepting an explicitIBlobStorageProviderparameter have been removed. Use options-based configuration viaFluentDynamoDbOptions.WithBlobStorage(provider)instead.BuildPk()/BuildSk()removed from generated Keys class — Computed key construction now happens via the unifiedPk(...)andSk(...)methods.Key()composite method removed from generated Keys class — UsePk(...)andSk(...)independently.- Passthrough
Pk(string)/Sk(string)methods removed for bare keys — Single-parameter passthrough methods that simply returned the input unchanged are no longer generated.
New Diagnostics
| Code | Severity | Description |
|---|---|---|
| FDDB104 | Info | Compound discrimination resolved overlap |
| FDDB120 | Error | Constant key conflicts with computed attribute |
| FDDB121 | Error | Prefix not applicable to constant key |
| FDDB122 | Error | Cannot extract from constant key |
| FDDB123 | Error | Empty constant key value |
| FDDB124 | Error | Extracted property conflicts with DynamoDbAttribute |
| FDDB125 | Error | Computed key property has redundant Prefix |
| FDDB126 | Error | Key property references non-compile-time-constant value |
Improvements
- Deterministic formatted output — All code paths applying format specifiers in computed fields now use
CultureInfo.InvariantCulture, ensuring locale-independent output regardless of host machine culture settings.
Bug Fixes
- Fixed FDDB110 warning emitted spuriously in transitive projects that don't define any DynamoDB entities.
- Fixed
Update()method parameter ordering placingKeyInputModebeforeKeyCondition, breaking existing code using positionalKeyConditionarguments. - Fixed discriminator regex not matching
{N:format}placeholders (e.g.,{0:yyyy-MM-dd}), producing incorrect derived patterns. - Fixed false FDDB090 diagnostics when format specifiers are present in computed key format strings.
- Fixed Keys builder pre-stringifying values before
string.Format, preventing format specifiers from being applied toIFormattabletypes likeDateOnlyandDateTime. - Fixed Update recomputation pre-stringifying source property values, ignoring format specifiers during computed field recalculation.
- Fixed multi-computed-field-target data loss when a source property contributes to multiple non-key computed fields.
- Fixed compound discrimination prefix subsumption, ExactMatch vs Complex, and spurious FDDB102 warnings.
- Fixed read-only key properties with non-const references generating uncompilable code (now emits FDDB126).
- Fixed non-string key types with prefix generating non-compilable code.
- Fixed DYNDB023 false positives for enum, extracted, and unmapped properties.
- Fixed typed overload not generated for single-source computed keys.
- Fixed
BlobData<T>internal methods inaccessible from generated code in external assemblies. - Fixed
Extract{Property}Components()using incorrect split index for format-string computed keys. - Fixed wildcard
*in complex key patterns not enforcing "one or more characters" semantics. - Fixed complex pattern exclusion producing tautological
Containscheck for bare separators.
v1.0.0
New Features
- Fluent API for DynamoDB operations — Type-safe, chainable builders for Get, Put, Update, Delete, Query, and Scan operations with three expression styles: lambda (preferred), format string, and manual.
- Source-generated entity mapping — AOT-compatible, reflection-free entity serialization and deserialization via
[DynamoDbTable]and[DynamoDbAttribute]annotations on partial classes. - Lambda expression support — Type-safe filter and condition expressions with support for
StartsWith,Contains,Between,AttributeExists,AttributeNotExists,Size,CompareTo, nested property access, and list indexing. - Composite entity support — Multi-item entity assembly via
[RelatedEntity]with hierarchical sort key patterns andToCompositeEntityAsync(). - Projection models — Read-only entity subsets via
[DynamoDbProjection]implementingIReadOnlyEntitywith automatic projection expression generation. - GSI/LSI index support — Declarative index configuration with
[GsiPartitionKey],[GsiSortKey], and[LsiSortKey]attributes, automatic index projections for single-entity tables, and multi-entity index consolidation. - Key condition shortcuts —
IfExists()andIfNotExists()builder methods andKeyConditionenum for simplified create-only, update-only, and delete-only patterns. - Conditional filter expressions — Natural
||and&&patterns with local boolean conditions for optional query filters evaluated at translation time. - Batch operations — Fluent builders for BatchGetItem, BatchWriteItem, and batch PartiQL with automatic retry of unprocessed items.
- Transaction support — Fluent builders for TransactWriteItems and TransactGetItems with idempotency token support.
- PartiQL support — SQL-like queries with automatic entity hydration via
ExecutePartiQL<T>(). - FluentResults API — Complete
Result<T>pattern alternative with typed error hierarchy (DynamoDbError,OptimisticLockingError,TransactionCancelledError, etc.) via theOproto.FluentDynamoDb.FluentResultspackage. - Dynamic fields —
[EnableDynamicFields]for capturing unmapped attributes with prefix-based discovery, typed Map operations, and bulk Set/Remove operations for sparse attribute patterns. - DynamicEntity/DynamicTable — Schema-less access to any DynamoDB table without entity class definitions.
- DateOnly and TimeOnly serialization — Native support with ISO 8601 defaults, custom format strings via
[DynamoDbAttribute(Format = "...")], and collection support. - String CompareTo in expressions — Range comparisons on string attributes using
x.SortKey.CompareTo("value") >= 0syntax. - IfNotExists with arithmetic — Counter patterns with non-zero defaults:
x.Count.IfNotExists(100) + 1. - Nested map and list expressions — Deep property access in filters, partial nested object updates, and list operations (
Append,Prepend,SetAt,RemoveAt). - Set operations —
Add()andDelete()builder methods for DynamoDB set manipulation. - Response metadata —
.Responseproperty on request builders exposingLastEvaluatedKey,ScannedCount,ConsumedCapacity, andHasMorePages. - Field-level encryption — KMS-based property encryption via
[Encrypted]attribute withAwsEncryptionSdkFieldEncryptor. - Blob storage integration — S3-backed large property storage via
[BlobStorage]attribute with automatic hydration. - Type-based table references —
[DynamoDbTable(typeof(MyTable))]for compile-time safe, refactoring-friendly table class references. - Custom index property naming —
Nameproperty on index attributes for controlling generated property names. - Pagination support — Encoded pagination tokens via
GetEncodedPaginationToken()andPaginate(PaginationRequest)for stateless pagination.
Breaking Changes
- Index attribute API redesigned —
[GlobalSecondaryIndex]and[LocalSecondaryIndex]replaced with[GsiPartitionKey],[GsiSortKey], and[LsiSortKey]. Key role and index type are encoded in the attribute name. - Null handling in update expressions —
nullnow consistently sets DynamoDB NULL. Use.NoUpdate()to skip a property update, and.Remove()to delete an attribute. [Queryable]attribute removed — Query capabilities are derived exclusively from[PartitionKey]and[SortKey]attributes.
Improvements
- Empty conditional expression handling — Operations with all-skip conditional filters execute without a filter instead of throwing an error.
- ExpressionCache bounded to 1024 entries — Prevents unbounded memory growth in long-running applications.