Skip to content

Commit 6dde680

Browse files
dmealingclaude
andcommitted
no-mistakes(document): Correct C# G7 — vanilla VO columns are patch-settable
G7's "Today" paragraph claimed a VO-typed column is skipped on PATCH as a deliberate cross-port Day-1 rule. Program D landed the opposite: the vanilla PATCH/PUT handler passes voFields into AppendPartialMergeLoop, which emits typed value-object arms AHEAD of the generic FindProperty arm (present value -> deserialize + recursive VO validation + assign the CLR nav; present-null clears a nullable column or 400s a @required one; absent -> untouched). Re-scope the entry to the true residual — VO columns on TPH entities, whose per-subtype path passes an empty VO list — and state explicitly that the vanilla-path behavior may mean the entry is already closed except for TPH, with the ruling deliberately deferred to issue #359 (closing needs Program D's intent, which this file does not own). Co-Authored-By: Claude Code <noreply@anthropic.com>
1 parent 3356853 commit 6dde680

1 file changed

Lines changed: 6 additions & 2 deletions

File tree

‎server/csharp/MetaObjects.Codegen/Generators/KNOWN_GAPS.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,17 @@ Update when a gap closes or a new one surfaces.
3737

3838
**Today.** We emit `{ "error": "not_found" }` for 404 and `{ "error": "validation", "message": "..." }` for the sort-validation 400. **FR-036 wired explicit body validation with the cross-port `{ "error": "validation" }` envelope:** a POST runs `Validator.TryValidateObject(input, ...)` and a PATCH runs `Validator.TryValidateProperty(value, ...)` per present value → 400 `{ "error": "validation" }` (ASP.NET minimal-API never runs DataAnnotations on its own, so the annotations were previously decorative at the wire tier). The `issues` array is still TS-only idiomatic (Tier 2).
3939

40-
### G7 — Value-object columns are non-PATCHable (deliberate, cross-port)
40+
### G7 — Value-object columns on TPH entities are still skipped on PATCH
4141

4242
**Contract.** A `field.object` column (a value-object mapped to jsonb, single or `@isArray`) is EF-mapped as an owned navigation (`.OwnsOne`/`.OwnsMany(...).ToJson`).
4343

4444
**`field.map` is not in this gap.** A map column is not a navigation — it is a scalar-shaped property carrying a value converter (G9) — so `FindProperty` resolves it and the generic merge arm writes it on PATCH. Map columns are patch-settable here, as on Java; Kotlin alone stages them out of its patch set (see its `KNOWN_GAPS.md`).
4545

46-
**Today.** The partial-PATCH merge loop keys off `entry.Metadata.FindProperty(prop.Name)`, which returns null for a navigation, so a VO-typed column is skipped on PATCH (present values too). This is a **deliberate cross-port Day-1 simplification**, consistent with Java + Kotlin (both exclude `ObjectField` from the patch set) — NOT a C#-specific bug (FR-036 assessed a C#-only fix and rejected it: it would break the api-contract byte-identical parity). Making VO-typed columns PATCHable (bind the owned nav via `entry.Navigation(...).CurrentValue`, cross-port) is a separately-scoped follow-up FR.
46+
**Today.** On the vanilla (non-TPH) PATCH/PUT handler a VO-typed column IS patch-settable. The handler passes the entity's VO fields into `AppendPartialMergeLoop` (`RoutesGenerator.cs:256`), which emits a Program D typed value-object arm for each one AHEAD of the generic `entry.Metadata.FindProperty(prop.Name)` arm — an owned navigation is invisible to `FindProperty`, so the generic scalar path alone would silently drop the column. Per arm: a present value is deserialized, recursively validated (`ValueObjectValidator.Validate`), and assigned to the CLR navigation property; a present `null` clears a nullable VO column — a nullable array-of-VO additionally takes a post-save raw UPDATE, since EF's `OwnsMany(...).ToJson` writes `[]` for a null collection nav rather than SQL NULL — or 400s a `@required` one; an absent key leaves the column untouched. This is the same Program D shipment Java's `KNOWN_GAPS.md` records as cross-port (TS / Python / Java / Kotlin / C#), gated by `fixtures/api-contract-conformance/jsonb/scenarios/jsonb-value-object-patch.yaml` in both lanes.
47+
48+
**Residual.** TPH only: the per-subtype partial-update path passes an empty VO list (`RoutesGenerator.cs:961`), so VO columns on a TPH-rooted entity are still skipped on PATCH — the same staging-out Java's entry records for TPH.
49+
50+
**Close status.** The vanilla-path behaviour above may mean this entry is already closed for everything except the TPH residual; that ruling is deliberately NOT made here because it needs Program D's intent, which this file does not own. It is filed for exactly that decision as [issue #359](https://github.com/metaobjectsdev/metaobjects/issues/359). Until ruled, the entry stays open against the TPH residual.
4751

4852
### G5 — `EfCoreFilterDispatch` ordered-comparison fallback
4953

0 commit comments

Comments
 (0)