Migration Guide
Key Changes in 7.0.0
The V7 release significantly impacted Marten internals and also included support for .NET 8 and and upgrade to Npgsql 8. In addition, Marten 7.0 requires at least PostgreSQL 12 because of the dependence upon sql/json constructs introduced in PostgreSQL 12.
Marten 7 includes a large overhaul of the LINQ provider support, with highlights including:
- Very significant improvements to querying through document child collections by being able to opt into JSONPath or containment operator querying in many cases. Early reports suggest an order of magnitude improvement in query times.
- GIST/GIN indexes should be effective with Marten queries again
- The
IMethodCallParser
interface changed slightly, and any custom implementations will have to be adjusted - Covers significantly more use cases within the LINQ
Where()
filtering Select()
support was widened to include constructor functions
The database connection lifetime logic in IDocumentSession
or IQuerySession
was changed from the original Marten 1-6 "sticky" connection behavior. Instead of Marten trying to keep a database connection open from first usage through any call to SaveChangesAsync()
, Marten is auto-closing the connection on every usage by default. This change should help reduce the overall number of open connections used at runtime, and help make Marten be more easily integrated into GraphQL solutions using the Hot Chocolate framework.
See Connection Handling for more information, including how to opt into the previous V6 and earlier "sticky" connection lifetime.
Marten 7 replaces the previous IRetryPolicy
mechanism for resiliency with built in support for Polly. See Resiliency Policies for more information.
Key Changes in 6.0.0
The V6 release lite motive is upgrading to .NET 7 and Npgsql 7. Besides that, we decided to align the event sourcing projections' naming and initializing document sessions. See the full release notes.
We tried to limit the number of breaking changes and mark methods with obsolete attributes to promote the new recommended way.
The scope of breaking changes is limited, but we highly encourage migrating from all obsolete usage to the new conventions.
Guide on migration from v5 to v6:
- We Dropped support of .NET Core 3.1 and .NET 5 following the Official .NET Support Policy. That allowed us to benefit fully from recent .NET improvements around asynchronous code, performance etc. Plus made maintenance easier by removing branches of code. If you're using those .NET versions, you need to upgrade to .NET 6 or 7.
- Upgraded Npgsql version to 7. If your project uses an explicitly lower version of Npgsql than 7, you'll need to bump it. We didn't face substantial issues this time, so you might not need to do around it, but you can double-check in the Npgsql 7 release notes for detailed information about breaking changes on their side.
- Generic
OpenSession
store options (OpenSession(SessionOptions options)
does not track changes by default. Previously, it was using identity map. Other overloads ofOpenSession
didn't change the default behavior but were made obsolete. We encourage using explicit session creation andLightweightSession
by default, as in the next major version, we plan to do the full switch. Read more about the Unit of Work mechanics. - Renamed asynchronous session creation to include explicit Serializable name.
OpenSessionAsync
was misleading, as the intention behind it was to enable proper handling of Postgres' serialized transaction level. Renamed the method toOpenSerializableSessionAsync
and added explicit methods for session types. Check more in handling Transaction Isolation Level. - Removed obsolete methods marked as to be removed in the previous versions.:
- Removed synchronous'BuildProjectionDaemon
from the
IDocumentStore` method. Use the asynchronous version instead. - Removed
Schema
fromIDocumentStore
. UseStorage
instead. - Replaced
GroupEventRange
inIAggregationRuntime
withSlicer
reference. - Removed unused
UseAppendEventForUpdateLock
setting. - Removed the
Searchable
method fromMartenRegistry
. UseIndex
instead. ASP.NET JSON streamingWriteById
is now using correctly customonFoundStatus
. We had the bug and always used the default status. It's enhancement but also technically a breaking change to the behavior. We also addedonFoundStatus
to other methods, so you could specify, e.g.201 Created
status for creating a new record.
- Removed synchronous'BuildProjectionDaemon
- Added Optimistic concurrency checks during documents' updates. Previously, they were only handled when calling the
Store
method; nowUpdate
uses the same logic. - Base state passed as parameter is returned from
AggregateStreamAsync
instead of null when the stream is empty.AggregateStreamAsync
allows passing the default state on which we're applying events. When no events were found, we were always returning null. Now we'll return the passed value. It is helpful when you filter events from a certain version or timestamp. It'll also be useful in the future for archiving scenarios - Ensured events with both
Create
andApply
in stream aggregation were handled only once. When you defined both Create and Apply methods for the specific event, both methods were called for the single event. That wasn't expected behavior. Now they'll be only handled once. - Added missing passing Cancellation Tokens in all async methods in public API. That ensures that cancellation is handled correctly across the whole codebase. Added the static analysis to ensure we won't miss them in the future.
- All the Critter Stack dependencies like
Weasel
,Lamar
,JasperFx.Core
,Oakton
, andJasperFx.CodeGeneration
were bumped to the latest major versions. If you use them explicitly, you'll need to align the versions.
Besides that, non-breaking but important changes to upgrade are:
- Added explicit
LightweightSession
andIdentitySession
creation methods toDocumentStore
. Previously you could createDirtyTrackedSession
explicitly. Now you can create all types of sessions explicitly. We recommend using them explicitly instead of the genericOpenSession
method. - Renamed aggregations into projections and
SelfAggregate
intoSnapshot
andLiveStreamAggregation
. The established terms in the Event Sourcing community are Projection and Snapshot. Even though our naming was more precise on the implementation behind the scenes, it could be confusing. We decided to align it with the common naming and be more explicit about the intention. Old methods were marked as obsolete and will be removed in the next major release.
Other notable new features:
- Added support for reusing Documents in the same async projection batch. By default, Marten does batch to handle multiple events for the projection in one update. When using
EventProjection
and updating data manually usingIDocumentOperations
, this may cause changes made for previous batch items not to be visible. Now you can opt-in for tracking documents by an identity within a batch using theEnableDocumentTrackingByIdentity
async projection option. Read more in related docs. - Enabled the possibility of applying projections with different Conjoined Tenancy scopes for projections. Enabled global projection for events with a conjoined tenancy style. Read more in multi-tenancy documentation
- Added automatic retries when schema updates are running in parallel. Marten locks the schema update using advisory locks. Previously when acquiring lock failed, then schema update also failed. Now it will be retried, which enables easier parallel automated tests and running schema migration during the startup for the containerized environment.
Key Changes in 5.0.0
V5 was a much smaller release for Marten than V4, and should require much less effort to move from V4 to V5 as it did from V2/3 to V4.
- The async daemon has to be explicitly added with a chained call to
AddAsyncDaemon(mode)
- The Marten integration with .Net bootstrapping now has the ability to split the Marten configuration for testing overrides or modular configuration
IInitialData
services are executed within IHost bootstrapping. See Initial Baseline Data.- New facility to apply all detected database changes on application startup.
- Ability to register multiple Marten document stores in one .Net IHost
- The "pre-built code generation" feature has a new, easier to use option in V5
- New "Optimized Artifact Workflow" option
- Some administrative or diagnostic methods that were previously on
IDocumentStore.Advanced
migrated to database specific access as shown here.
Key Changes in 4.0.0
V4 was a very large release for Marten, and basically every subsystem was touched at some point. When you are upgrading from V2/3 to V4 -- and even earlier alphas or RC releases of 4.0 -- you will need to run a database migration as part of your migration to V4.
Other key, breaking changes:
- All schema management methods, including assertions on the schema, are now asynchronous. We had to do this for Npgsql connection multiplexing.
- The compiled query syntax changed
- The event store support has quite a few additions
- Projections in Marten have moved to an all new programming model. Some of it is at least similar, but read the documentation on projection types before moving a Marten application over
- The async daemon was completely rewritten, and is now about to run in application clusters and handle multi-tenancy
- A few diagnostic methods moved within the API
- Document types need to be public now, and Marten will alert you if document types are not public
- The dynamic code in Marten moved to a runtime code generation model. If this is causing you any issues with cold start times or memory usage due to Roslyn misbehaving (this is not consistent), there is the new "generate ahead model" as a workaround.
- If an application bootstraps Marten through the
IServiceCollection.AddMarten()
extension methods, the default logging in Marten is through the standardILogger
of the application - In order to support more LINQ query permutations, LINQ queries are temporarily not using the GIN indexable operators on documents that have
GinIndexJsonData()
set. Support for this can be tracked here - PLV8 support is disabled by default and moved to a separate package. If an application was setting
StoreOptions.PLV8Enabled = false
to disable PLV8, that line should be removed as the setting no longer exists. If an application hadStoreOptions.PLV8Enabled = true
and was using PLV8, you will need to add the Marten.PLv8 package.
Key Changes in 3.0.0
Main goal of this release was to accommodate the Npgsql 4.* dependency.
Besides the usage of Npgsql 4, our biggest change was making the default schema object creation mode to CreateOrUpdate
. Meaning that Marten even in its default mode will not drop any existing tables, even in development mode. You can still opt into the full "sure, I’ll blow away a table and start over if it’s incompatible" mode, but we felt like this option was safer after a few user problems were reported with the previous rules. See schema migration and patches for more information.
We also aligned usage of EnumStorage
. Previously, Enum duplicated fields was always stored as varchar
. Now it's using setting from JsonSerializer
options - so by default it's integer
. We felt that it's not consistent to have different default setting for Enums stored in json and in duplicated fields.
See full list of the fixed issues on GitHub.
You can also read more in Jeremy's blog post from.
Migration from 2.*
- To keep Marten fully rebuilding your schema (so to allow Marten drop tables) set store options to:
AutoCreateSchemaObjects = AutoCreate.All
- To keep enum fields being stored as
varchar
set store options to:
DuplicatedFieldEnumStorage = EnumStorage.AsString;
- To keep duplicated DateTime fields being stored as
timestamp with time zone
set store options to:
DuplicatedFieldUseTimestampWithoutTimeZoneForDateTime = false;