ADR-0030: construct DTO projections through the existing EF shaper¶
Status: accepted for the DTO projection increment. All 648 provider units, 218 live integration and 69 selected EF checks pass locally on 2026-10-11. FS-13 aggregates remain separate; see projection evidence.
Use a bounded expression visitor for result construction: mapped scalar leaves, constructor calls, member assignments, nested DTOs, EF execution parameters and root structural shapers. Retain the existing EF materialization pipeline, row buffer indexes, conversions, graph identity guards and state manager. Deduplicate selected columns by bound property and preserve their stable EF indexes.
An ordinary-node projection with no store values returns a literal row witness to preserve cardinality. Edge/native-reference projections retain hidden key and diagnostic columns through GraphReadBinding. Non-identity projections with Include reject because existing Include fixup expects an entity result. Row-dependent method calls and arithmetic do not fall back to client evaluation.
Pinned EF ExpressionTreeFuncletizer source confirms that TryHandleNonEvaluatableAsRoot preserves noncaptured NewExpression/MemberInitExpression roots but allows captured constructors to become query parameters. Read those through QueryContext.Parameters in the compiled shaper, including DTO-typed parameters; no evaluatable-expression service replacement or custom cache is necessary. Arbitrary object constants are not introduced into the cache. EF remains responsible for row-independent parameter extraction and its object-sharing semantics.
The projection guide states supported shapes, tracking and execution boundaries. Acceptance requires exact generated Cypher, captured-value rebinding, scalar-only and nested-entity tracking modes, nullable/converted/shadow values, constant/empty cardinality, constructor-error recovery, preserved relationship guards and unchanged upstream projection assertions against the control fixture.