Present a projection to code typed against the shared catalog entities.
The two casts below are the ONLY place this narrowing happens, deliberately, so the reasoning
sits in one auditable spot. A projection carries every property the read sites touch and none of
BaseEntity's behaviour — no Save(), no Fields, no dirty tracking. That is safe here and
nowhere else, because reads are all this cache serves: the per-connection write path holds real
entity rows and never receives one of these.
Calling .Save() on the result would throw at runtime rather than corrupt anything, which is the
failure mode to want if this contract is ever broken.
Present a projection to code typed against the shared catalog entities.
The two casts below are the ONLY place this narrowing happens, deliberately, so the reasoning sits in one auditable spot. A projection carries every property the read sites touch and none of
BaseEntity's behaviour — noSave(), noFields, no dirty tracking. That is safe here and nowhere else, because reads are all this cache serves: the per-connection write path holds real entity rows and never receives one of these.Calling
.Save()on the result would throw at runtime rather than corrupt anything, which is the failure mode to want if this contract is ever broken.