Release v15.39.0
Summary
A model-bound or declarative projection could silently corrupt a read model property. Whenever a projection subscribed to an event — often only to [Count] it, [Add] from it, or [Join] on it — and that event happened to carry a property with the same name as one the read model set explicitly, name-based AutoMap would overwrite the explicit value with the unrelated event's. The developer did nothing wrong, and the only workaround was to turn AutoMap off for the whole read model and hand-map every property.
This makes AutoMap respect explicit intent, in two layers that behave identically across model-bound, declarative, and PDL projections:
- An event a projection subscribes to only to aggregate (
[Count]/[Increment]/[Decrement]/[Add]/[Subtract]) no longer contributes its other properties to AutoMap. This is the common case — pulling an event in just to count it — and it now needs no annotation. - A new property-level
[NoAutoMap]covers the cases the framework cannot infer — a value-mapped ([SetFrom]) or[Join]ed event that collides — by excluding a single property from AutoMap while everything else keeps mapping.
It also fixes an unrelated gap in the in-process testing harness that prevented it from driving standalone fluent projections.
Added
- Property-level
[NoAutoMap]— apply[NoAutoMap]to a single read model property (or record parameter) instead of the whole read model, to exclude just that property from AutoMap while every other property keeps mapping. Use it when an event you subscribe to for a specific value ([SetFrom]) or a[Join]happens to carry an identically named property that would otherwise overwrite your explicitly sourced value (#3444)
Changed
- AutoMap no longer copies the other properties of an event a read model subscribes to only to aggregate (
[Count]/[Increment]/[Decrement]/[Add]/[Subtract]). Previously, aggregating an event also name-mapped its unrelated properties onto the read model, which could silently overwrite explicitly sourced values; aggregating an event now contributes only the aggregate (#3444)
Fixed
ReadModelScenario<T>no longer throws (The number of generic arguments provided doesn't equal the arity of the generic type definition) on the first access toInstance/Instanceswhen the read model under test is projected by a standaloneIProjectionFor<T>class