Skip to main content

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 new KeyInputMode enum (Auto, Value, Raw) with configurable defaults through FluentDynamoDbOptions.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 like int, enum, Guid, DateTime, DateOnly, and TimeOnly.
  • 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. DefaultKmsKeyResolver accepts a new aliasKeyMap parameter 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 DiscriminatorPattern specification 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#* vs TENANT#*). Uses positional IndexOf-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(...) and Sk(...) methods, handling prefix-based, computed, and constant key patterns uniformly.

Breaking Changes

  • IKmsKeyResolver is now asyncResolveKeyId(string? contextId) is replaced by ResolveKeyIdAsync(string? contextId, string? keyAlias, CancellationToken) returning Task<string>. All custom implementations must be updated.
  • DefaultKmsKeyResolver constructor updated — The existing contextKeyMap parameter is now named explicitly, and a new optional aliasKeyMap parameter is available for per-alias key resolution.
  • IBlobStorageProvider parameter overloads removed — All terminal method overloads accepting an explicit IBlobStorageProvider parameter have been removed. Use options-based configuration via FluentDynamoDbOptions.WithBlobStorage(provider) instead.
  • BuildPk()/BuildSk() removed from generated Keys class — Computed key construction now happens via the unified Pk(...) and Sk(...) methods.
  • Key() composite method removed from generated Keys class — Use Pk(...) and Sk(...) 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

CodeSeverityDescription
FDDB104InfoCompound discrimination resolved overlap
FDDB120ErrorConstant key conflicts with computed attribute
FDDB121ErrorPrefix not applicable to constant key
FDDB122ErrorCannot extract from constant key
FDDB123ErrorEmpty constant key value
FDDB124ErrorExtracted property conflicts with DynamoDbAttribute
FDDB125ErrorComputed key property has redundant Prefix
FDDB126ErrorKey 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 placing KeyInputMode before KeyCondition, breaking existing code using positional KeyCondition arguments.
  • 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 to IFormattable types like DateOnly and DateTime.
  • 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 Contains check 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 and ToCompositeEntityAsync().
  • Projection models — Read-only entity subsets via [DynamoDbProjection] implementing IReadOnlyEntity with 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 shortcutsIfExists() and IfNotExists() builder methods and KeyCondition enum 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 the Oproto.FluentDynamoDb.FluentResults package.
  • 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") >= 0 syntax.
  • 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 operationsAdd() and Delete() builder methods for DynamoDB set manipulation.
  • Response metadata.Response property on request builders exposing LastEvaluatedKey, ScannedCount, ConsumedCapacity, and HasMorePages.
  • Field-level encryption — KMS-based property encryption via [Encrypted] attribute with AwsEncryptionSdkFieldEncryptor.
  • 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 namingName property on index attributes for controlling generated property names.
  • Pagination support — Encoded pagination tokens via GetEncodedPaginationToken() and Paginate(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 expressionsnull now 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.