9.0: widen document Revision int → long (#3733)#4377
Merged
Conversation
#3733) Breaking change for Marten 9.0. The numeric revision tracking column (`mt_version` when `UseNumericRevisions` is on) is now `bigint` rather than `integer`, and all .NET-side surfaces that carry the revision widen from `int` to `long`: - `Marten.Metadata.IRevisioned.Version` - `DocumentMetadata.CurrentRevision` - `IRevisionedOperation.Revision` - `IDocumentSession.UpdateRevision` / `TryUpdateRevision` parameter - `IDocumentStorage<T>.Store(IMartenSession, T, long)` - `VersionTracker.RevisionFor` / `StoreRevision` / `RevisionsFor` - `MetadataColumn<int>` → `MetadataColumn<long>` for `RevisionColumn` - Bulk-loader expected-version argument (`bigint`) - `mt_upsert_*` / `mt_update_*` / `mt_overwrite_*` function signatures and local variables (`final_version` / `current_version`) now `BIGINT` - `MartenRegistry.MetadataConfig.Revision` exposed as `Column<long>` Schema migration from a Marten 8 deployment is non-destructive: the existing `integer` column is widened in place via `ALTER COLUMN ... TYPE bigint`, preserving all stored revision values. Switching from a Guid-versioned column to numeric revisions still drops and recreates the column. Also fixes an NRE in `MetadataColumn.Member.set` when the rejected member-type diagnostic ran on the first (null `_member`) assignment. User-visible code that implements `IRevisioned` or carries a `[Version]` numeric property must widen the property to `long`. The migration guide (#4355) covers this. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
…3733 CI fix) CI on #4377 surfaced one missed [Version]-annotated property: the test class MyAggregateWithDifferentVersionProperty had [Version] public int SpecialVersion { get; set; } The original sed-based widening only matched the literal "public int Version" property name; this one slipped through because the property is called SpecialVersion. Widened to long. Also tightened src/Marten/Schema/VersionAttribute.cs: * The Modify() branch that accepted int is removed — [Version] on a Marten 9 numeric-revisioning property must be long, since MetadataColumn<long> rejects an int member at registration time. * A dedicated diagnostic now fires when a user annotates an int property, naming the declaring type/member and pointing at the migration-guide section so the fix is obvious from the stack trace. * The catch-all error message dropped "int" from the supported types list to match the new contract. Verified locally: * The previously-failing test EventSourcingTests.Aggregation.setting_version_number_on_aggregate.set_version_on_aggregate_with_explicit_Version_attribute passes. * Full EventSourcingTests on net9.0: 1274 passed, 2 skipped, 0 failed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
jeremydmiller
added a commit
that referenced
this pull request
May 20, 2026
… (#4534) * Marten docs: rewrite stale IRevisioned int->long migration-guide section for the #4533 revert An early 9.0 alpha widened IRevisioned.Version to long; #4533 reverted that before rc.1 (IRevisioned stays int, V8-compatible) and added ILongVersioned (long) for MultiStreamProjection documents whose Version is the global event sequence number. The migration guide still told users to widen Version to long. Rewrite the section to lead with the reversal, introduce ILongVersioned with the Int32-overflow rationale, and replace the widen-to-long example with a correct IRevisioned(int)/ILongVersioned(long) pair. Every Before|After type in the table was verified against origin/master source: IRevisioned.Version is int (unchanged); DocumentMetadata.CurrentRevision, UpdateRevision/TryUpdateRevision parameters, IRevisionedOperation.Revision and the m.Revision metadata column are long (and source-compatible via int->long). Dropped the stale claim that MapTo to an int property throws (RevisionColumn now accepts int or long). References updated to #4533 / #4526 / #4528 / #348; #3733 / #4377 are historical. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Marten docs: regenerate concurrency.md sample_versioned_reservation snippet (int Version) The embedded sample_versioned_reservation snippet still showed long Version even though its source (src/Marten.Testing/Examples/RevisionedDocuments.cs) was already reverted to int by #4533. Regenerated via mdsnippets so the embed matches source. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3733.
Breaking change for Marten 9.0. The numeric revision tracking column (
mt_versionwhenUseNumericRevisionsis enabled) widens fromintegertobigint, and every .NET-side surface that carries a document revision moves frominttolong.Why
intcapped Marten's numeric-revision tracking at ~2.1B updates per document — well within reach for high-throughput inline projections and event-sourced aggregates that snapshot per event.longremoves the ceiling without changing the public surface beyond the type widening.What changed (Marten core)
Marten.Metadata.IRevisioned.VersionintlongDocumentMetadata.CurrentRevisionintlongIRevisionedOperation.RevisionintlongIDocumentSession.UpdateRevision<T>(entity, revision)int revisionlong revisionIDocumentSession.TryUpdateRevision<T>(entity, revision)int revisionlong revisionIDocumentStorage<T>.Store(IMartenSession, T, int)intlongVersionTracker.RevisionFor/StoreRevision/RevisionsForintlongMetadataColumn<int>forRevisionColumn<int><long>MartenRegistry.MetadataConfig.RevisionColumn<int>Column<long>mt_doc_*.mt_version(numeric revisions)integerbigintmt_upsert_*/mt_update_*/mt_overwrite_*revision arg + return + localsINTEGERBIGINTNpgsqlDbType.IntegerNpgsqlDbType.BigintSchema migration
Non-destructive widening from a Marten 8 deployment:
RevisionColumn.AlterColumnTypeSqlnow emitsALTER TABLE … ALTER COLUMN mt_version TYPE bigint;when it sees an existingintegercolumn. Existing revision values are preserved. Switching from a Guid-versioned column (uuid) to numeric revisions still drops and recreates the column as before.Bonus
MetadataColumn<T>.Member.setwhen the diagnostic message for a type-mismatched member ran on the first assignment (the message referenced the still-null_memberfield — now references the incomingvalue).What user code needs to do
: IRevisionedimplementation: widen theVersionproperty tolong.[Version]-annotated numeric property used withUseNumericRevisions: widen tolong.m.Revision.MapTo(x => x.SomeProperty)configuration: the target property must belong.This is the documented Marten 8 → 9 migration shape; the migration guide section is being tracked in #4355.
Verification
DocumentDbTestson net9.0: 968 passed, 1 skipped, 0 failed (~58s)EventSourcingTestssubset that touchesIRevisioned(when_finding_the_last_good_aggregation,using_explicit_code_for_live_aggregation,stream_compacting,fetching_live_aggregates,fetching_inline_aggregates): 81 passedPatchingTests(Bug_3261_patch_plus_revisions): 1 passedCoreTestsrevision-related: 6 passedDocumentDbTests/Concurrency/numeric_revisioning: 22 passedDocumentDbTests/Writing/bulk_loading_Tests.overwrite_if_version_matches_respects_expected_revision: passedThe committed TestCodeGen-validated
RevisionedDocProvider1212098993.cswas regenerated from this widening (now readslong).Out of scope
JasperFx.IRevisioned(a duplicate ofMarten.Metadata.IRevisionedin the JasperFx package) still hasint Version. The three test classes that resolved to JasperFx's interface viausing JasperFx;are now explicitly qualified toMarten.Metadata.IRevisioned. Deduplicating the two interfaces is a follow-up for the Marten 9.0 dedupe-with-JasperFx pass (umbrella [Master] Marten 9.0 #4349).Test plan
TestCodeGennuke task passes (the committed regen file matches the widened codegen output)docs/documents/concurrency.mdint Versionsnippets updated)🤖 Generated with Claude Code