You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
WriteSingle / StreamOne<T> throws at runtime when the queryable carries a Select() projection, because the ETag support appends an mt_version column to a select that has no data column.
Regression introduced by #5027 / PR #5030 (44f9b44a2), first shipped in 9.18.0. Still present on master at 0e8daed37.
Repro
awaitusingvarquery=store.QuerySession();varcontext=newDefaultHttpContext{Response={Body=newMemoryStream()}};awaitquery.Query<Issue>().Where(x =>x.Id==issue.Id).Select(x =>new{x.Description})// <-- any Select() projection.WriteSingle(context,emitETag:true);// emitETag: true is the default
System.IndexOutOfRangeException : Field not found in row: data
at Npgsql.BackendMessages.RowDescriptionMessage.GetFieldIndex(String name)
at Npgsql.NpgsqlDataReader.GetOrdinal(String name)
at Marten.Services.JsonStreamingExtensions.StreamOneWithVersion(DbDataReader reader, ...)
at Marten.Internal.Sessions.QuerySession.StreamOneWithVersion(DbCommand command, ...)
at Marten.Linq.MartenLinqQueryProvider.StreamOneWithVersion[T](Expression expression, ...)
at Marten.AspNetCore.QueryableExtensions.WriteSingle[T](IQueryable`1 queryable, ...)
Passing emitETag: false works, which is the current workaround — it routes to the plain StreamJsonFirstOrDefault path that never appends the version column.
Root cause
In MartenLinqQueryProvider.StreamOneWithVersion<T>, T is the projected type once a Select() is in play — an anonymous type, or any DTO — not the mapped document type:
FindMapping on an unmapped type returns a freshly-built DocumentMapping whose Metadata.Version.Enabled defaults to true, so the guard passes. VersionSelectClause then appends d.mt_version as mt_etag_version to a select clause that projects scalars rather than the data column, and the reader's GetOrdinal("data") blows up.
The check needs to key off whether the select clause actually produces the document payload (or off the source document type behind the projection), not off a mapping looked up by the projected type.
Scope
Affects WriteSingle and therefore StreamOne<T> whenever a Select() projection is combined with the default emitETag: true.
Summary
WriteSingle/StreamOne<T>throws at runtime when the queryable carries aSelect()projection, because the ETag support appends anmt_versioncolumn to aselectthat has nodatacolumn.Regression introduced by #5027 / PR #5030 (
44f9b44a2), first shipped in 9.18.0. Still present on master at0e8daed37.Repro
Passing
emitETag: falseworks, which is the current workaround — it routes to the plainStreamJsonFirstOrDefaultpath that never appends the version column.Root cause
In
MartenLinqQueryProvider.StreamOneWithVersion<T>,Tis the projected type once aSelect()is in play — an anonymous type, or any DTO — not the mapped document type:FindMappingon an unmapped type returns a freshly-builtDocumentMappingwhoseMetadata.Version.Enableddefaults totrue, so the guard passes.VersionSelectClausethen appendsd.mt_version as mt_etag_versionto a select clause that projects scalars rather than thedatacolumn, and the reader'sGetOrdinal("data")blows up.The check needs to key off whether the select clause actually produces the document payload (or off the source document type behind the projection), not off a mapping looked up by the projected type.
Scope
WriteSingleand thereforeStreamOne<T>whenever aSelect()projection is combined with the defaultemitETag: true.Versionbranch.StreamOne<TDoc, TOut>compiled-query overload does not participate in ETag handling and is unaffected.mt_versionread) this combination worked.Verification
Reproduced on a clean checkout of master at
de63fc5ed— i.e. before #5121 — so this is not related to that change. Also reproduces on0e8daed37.Noted while reviewing #5121; deliberately left out of the follow-up (#5157) since it is a separate pre-existing defect.