Top Related Projects
EventStoreDB, the event-native database. Designed for Event Sourcing, Event-Driven, and Microservices architectures
A persistence agnostic Event Store for .NET
EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
Npgsql is the .NET data provider for PostgreSQL.
Canonical actor model implementation for .NET with local + distributed actors in C# and F#.
Simple, unambitious mediator implementation in .NET
Quick Overview
Marten is a .NET library that provides document database and event store capabilities using PostgreSQL as the underlying storage engine. It offers a flexible and powerful way to work with document data and event sourcing in .NET applications, leveraging the robustness and features of PostgreSQL.
Pros
- Combines document database and event store functionality in a single library
- Utilizes PostgreSQL, benefiting from its reliability, performance, and advanced features
- Provides a clean, intuitive API for working with documents and events
- Supports LINQ queries for document data retrieval
Cons
- Requires PostgreSQL as the backend, which may not be suitable for all use cases
- Learning curve for developers unfamiliar with document databases or event sourcing
- Limited ecosystem compared to more established document databases like MongoDB
Code Examples
- Creating and saving a document:
using var store = DocumentStore.For("connection_string");
using var session = store.LightweightSession();
var user = new User { Name = "John Doe", Email = "john@example.com" };
session.Store(user);
await session.SaveChangesAsync();
- Querying documents using LINQ:
using var session = store.QuerySession();
var users = await session.Query<User>()
.Where(u => u.Email.EndsWith("@example.com"))
.ToListAsync();
- Working with the event store:
using var session = store.LightweightSession();
var stream = session.Events.StartStream<User>(user.Id);
stream.AppendEvent(new UserRegistered(user.Id, user.Name));
stream.AppendEvent(new EmailChanged(user.Id, "newemail@example.com"));
await session.SaveChangesAsync();
Getting Started
-
Install the Marten NuGet package:
dotnet add package Marten
-
Configure Marten in your application:
using Marten;
var store = DocumentStore.For(options =>
{
options.Connection("your_connection_string");
options.AutoCreateSchemaObjects = AutoCreate.All;
});
services.AddMarten(store);
- Start using Marten in your code:
public class UserService
{
private readonly IDocumentSession _session;
public UserService(IDocumentSession session)
{
_session = session;
}
public async Task CreateUser(User user)
{
_session.Store(user);
await _session.SaveChangesAsync();
}
}
Competitor Comparisons
EventStoreDB, the event-native database. Designed for Event Sourcing, Event-Driven, and Microservices architectures
Pros of EventStore
- Purpose-built for event sourcing with optimized read and write operations
- Supports clustering for high availability and scalability
- Provides a built-in HTTP API and various client SDKs
Cons of EventStore
- Requires separate infrastructure and maintenance
- Steeper learning curve for teams new to event sourcing
- Limited querying capabilities compared to document databases
Code Comparison
EventStore (C#):
var connection = EventStoreConnection.Create(connectionSettings, new Uri("tcp://localhost:1113"));
await connection.ConnectAsync();
var eventData = new EventData(Guid.NewGuid(), "UserCreated", true, Encoding.UTF8.GetBytes(json), null);
await connection.AppendToStreamAsync("user-1", ExpectedVersion.Any, eventData);
Marten (C#):
using (var session = store.OpenSession())
{
session.Events.Append("user-1", new UserCreated { Name = "John Doe" });
await session.SaveChangesAsync();
}
Summary
EventStore is a specialized event sourcing database, offering robust features for event-driven architectures. Marten, built on PostgreSQL, provides a more flexible approach, combining document database capabilities with event sourcing. EventStore excels in pure event sourcing scenarios, while Marten offers a broader range of data persistence options within a single system.
A persistence agnostic Event Store for .NET
Pros of NEventStore
- Mature and battle-tested event sourcing solution with a longer history
- Supports multiple storage backends (SQL Server, MySQL, PostgreSQL, etc.)
- Provides a simple and straightforward API for event sourcing
Cons of NEventStore
- Less active development and community support compared to Marten
- Limited built-in support for advanced querying and projections
- Lacks integrated document database functionality
Code Comparison
NEventStore:
var store = Wireup.Init()
.UsingInMemoryPersistence()
.Build();
using (var stream = store.OpenStream(streamId))
{
stream.Add(new EventMessage { Body = myEvent });
stream.CommitChanges(Guid.NewGuid());
}
Marten:
using (var session = store.OpenSession())
{
session.Events.Append(streamId, myEvent);
session.SaveChanges();
}
Summary
NEventStore is a mature event sourcing solution with multi-database support, while Marten offers a more modern approach with integrated document database capabilities. NEventStore provides a simple API but lacks some advanced features found in Marten. The code comparison shows that both libraries offer straightforward ways to append events to streams, with Marten's syntax being slightly more concise.
EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
Pros of EF Core
- Extensive documentation and large community support
- Seamless integration with other Microsoft technologies
- Supports a wide range of database providers
Cons of EF Core
- Can be slower for complex queries compared to raw SQL
- Steeper learning curve for developers new to ORM concepts
- May generate inefficient SQL in some scenarios
Code Comparison
Marten:
var session = store.LightweightSession();
session.Store(new User { Name = "John" });
await session.SaveChangesAsync();
EF Core:
using var context = new MyDbContext();
context.Users.Add(new User { Name = "John" });
await context.SaveChangesAsync();
Both ORMs provide similar functionality for basic CRUD operations, but Marten's API is more focused on document-style persistence, while EF Core follows a traditional relational database approach. Marten excels in scenarios involving complex document structures and event sourcing, whereas EF Core is more suitable for applications with complex relational data models and those heavily integrated with the .NET ecosystem.
Npgsql is the .NET data provider for PostgreSQL.
Pros of Npgsql
- More mature and widely adopted ADO.NET data provider for PostgreSQL
- Supports a broader range of PostgreSQL features and data types
- Better performance for raw SQL queries and basic CRUD operations
Cons of Npgsql
- Lacks built-in document database capabilities
- Requires more boilerplate code for complex operations
- No native support for event sourcing or CQRS patterns
Code Comparison
Npgsql (basic query):
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
using (var cmd = new NpgsqlCommand("SELECT * FROM users WHERE id = @id", conn))
{
cmd.Parameters.AddWithValue("id", userId);
using (var reader = cmd.ExecuteReader())
{
// Process results
}
}
}
Marten (document query):
using (var session = store.OpenSession())
{
var user = session.Load<User>(userId);
// User object is loaded and ready to use
}
Marten provides a more streamlined API for document database operations, while Npgsql offers lower-level access to PostgreSQL features. Marten builds on top of Npgsql, adding document database and event sourcing capabilities, making it more suitable for complex domain-driven design scenarios. Npgsql is better for projects that require fine-grained control over PostgreSQL features and optimized performance for relational data access.
Canonical actor model implementation for .NET with local + distributed actors in C# and F#.
Pros of Akka.NET
- Robust actor model implementation for building distributed systems
- Supports various patterns like clustering, persistence, and streams
- Large ecosystem with extensive documentation and community support
Cons of Akka.NET
- Steeper learning curve due to actor model complexity
- Potentially higher resource usage for smaller applications
- Less focused on document database functionality compared to Marten
Code Comparison
Akka.NET (Actor definition):
public class MyActor : ReceiveActor
{
public MyActor()
{
Receive<string>(message => Console.WriteLine($"Received: {message}"));
}
}
Marten (Document storage):
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
}
using (var session = store.LightweightSession())
{
session.Store(new User { Name = "John Doe" });
session.SaveChanges();
}
While Akka.NET focuses on actor-based concurrency and distributed systems, Marten specializes in document database operations using PostgreSQL. Akka.NET is more suitable for complex, distributed applications, while Marten excels in scenarios requiring document storage and querying capabilities.
Simple, unambitious mediator implementation in .NET
Pros of MediatR
- Lightweight and focused on the mediator pattern, making it easier to implement and understand
- Provides a clean separation of concerns, enhancing code organization and maintainability
- Supports both synchronous and asynchronous request handling
Cons of MediatR
- Lacks built-in persistence capabilities, requiring additional setup for data storage
- Does not provide document database features or event sourcing out of the box
- May introduce additional complexity for smaller projects with simple CRUD operations
Code Comparison
MediatR:
public class PingHandler : IRequestHandler<Ping, string>
{
public Task<string> Handle(Ping request, CancellationToken cancellationToken)
{
return Task.FromResult("Pong");
}
}
Marten:
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
}
documentSession.Store(new User { Name = "John Doe" });
await documentSession.SaveChangesAsync();
While MediatR focuses on implementing the mediator pattern for in-memory message handling, Marten provides document database functionality with built-in persistence. MediatR is more suitable for organizing application logic, while Marten excels in data storage and retrieval scenarios.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Marten
.NET Transactional Document DB and Event Store on PostgreSQL
The Marten library provides .NET developers with the ability to use the proven PostgreSQL database engine and its fantastic JSON support as a fully fledged document database. The Marten team believes that a document database has far reaching benefits for developer productivity over relational databases with or without an ORM tool.
Marten also provides .NET developers with an ACID-compliant event store with user-defined projections against event streams.
Access docs here and v3.x docs here.
Support Plans
While Marten is open source, JasperFx Software offers paid support and consulting contracts for Marten.
Help us keep working on this project ð
Become a Sponsor on GitHub by sponsoring monthly or one time.
Past Sponsors
Working with the Code
Before getting started you will need the following in your environment:
1. .NET SDK 8.0+
Available here
2. PostgreSQL 12 or above database
The fastest possible way to develop with Marten is to run PostgreSQL in a Docker container. Assuming that you have Docker running on your local box, type:
docker-compose up
or
dotnet run --framework net6.0 -- init-db
at the command line to spin up a Postgresql database withThe default Marten test configuration tries to find this database if no
PostgreSQL database connection string is explicitly configured following the steps below:
PLV8
If you'd like to use Patching Api you need to enable the PLV8 extension inside of PostgreSQL for running JavaScript stored procedures for the nascent projection support.
Ensure the following:
- The login you are using to connect to your database is a member of the
postgres
role - An environment variable of
marten_testing_database
is set to the connection string for the database you want to use as a testbed. (See the Npgsql documentation for more information about PostgreSQL connection strings ).
Help with PSQL/PLV8
- On Windows, see this link for pre-built binaries of PLV8
- On *nix, check marten-local-db for a Docker based PostgreSQL instance including PLV8.
Test Config Customization
Some of our tests are run against a particular PostgreSQL version. If you'd like to run different database versions, you can do it by setting POSTGRES_IMAGE
env variables, for instance:
POSTGRES_IMAGE=postgres:15.3-alpine docker compose up
Tests explorer should be able to detect database version automatically, but if it's not able to do it, you can enforce it by setting postgresql_version
to a specific one (e.g.)
postgresql_version=15.3
Once you have the codebase and the connection string file, run the build command or use the dotnet CLI to restore and build the solution.
You are now ready to contribute to Marten.
See more in Contribution Guidelines.
Tooling
- Unit Tests rely on xUnit and Shouldly
- Bullseye is used for build automation.
- Node.js runs our Mocha specs.
- Storyteller for some of the data intensive automated tests
Build Commands
Description | Windows Commandline | PowerShell | Linux Shell | DotNet CLI |
---|---|---|---|---|
Run restore, build and test | build.cmd | build.ps1 | build.sh | dotnet build src\Marten.sln |
Run all tests including mocha tests | build.cmd test | build.ps1 test | build.sh test | dotnet run --project build/build.csproj -- test |
Run just mocha tests | build.cmd mocha | build.ps1 mocha | build.sh mocha | dotnet run --project build/build.csproj -- mocha |
Run StoryTeller tests | build.cmd storyteller | build.ps1 storyteller | build.sh storyteller | dotnet run --project build/build.csproj -- storyteller |
Open StoryTeller editor | build.cmd open_st | build.ps1 open_st | build.sh open_st | dotnet run --project build/build.csproj -- open_st |
Run docs website locally | build.cmd docs | build.ps1 docs | build.sh docs | dotnet run --project build/build.csproj -- docs |
Publish docs | build.cmd publish-docs | build.ps1 publish-docs | build.sh publish-docs | dotnet run --project build/build.csproj -- publish-docs |
Run benchmarks | build.cmd benchmarks | build.ps1 benchmarks | build.sh benchmarks | dotnet run --project build/build.csproj -- benchmarks |
Note: You should have a running Postgres instance while running unit tests or StoryTeller tests.
xUnit.Net Specs
The tests for the main library are now broken into three testing projects:
CoreTests
-- basic services like retries, schema management basicsDocumentDbTests
-- anything specific to the document database features of MartenEventSourcingTests
-- anything specific to the event sourcing features of Marten
To aid in integration testing, Marten.Testing has a couple reusable base classes that can be use to make integration testing through Postgresql be more efficient and allow the xUnit.Net tests to run in parallel for better throughput.
IntegrationContext
-- if most of the tests will use an out of the box configuration (i.e., no fluent interface configuration of any document types), use this base type. Warning though, this context type will not clean out the mainpublic
database schema between runs, but will delete any existing dataDestructiveIntegrationContext
-- similar toIntegrationContext
, but will wipe out any and all Postgresql schema objects in thepublic
schema between tests. Use this sparingly please.OneOffConfigurationsContext
-- if a test suite will need to frequently re-configure theDocumentStore
, this context is appropriate. You do not need to decorate any of these test classes with the[Collection]
attribute. This fixture will use an isolated schema using the name of the test fixture type as the schema nameBugIntegrationContext
-- the test harnesses for bugs tend to require customDocumentStore
configuration, and this context is a specialization ofOneOffConfigurationsContext
for the bugs schema.StoreFixture
andStoreContext
are helpful if a series of tests use the same customDocumentStore
configuration. You'd need to write a subclass ofStoreFixture
, then useStoreContext<YourNewStoreFixture>
as the base class to share theDocumentStore
between test runs with xUnit.Net's shared context (IClassFixture<T>
)
Mocha Specs
Refer to the build commands section to look up the commands to run Mocha tests. There is also npm run tdd
to run the mocha specifications
in a watched mode with growl turned on.
Note: remember to run
npm install
Storyteller Specs
Refer to build commands section to look up the commands to open the StoryTeller editor or run the StoryTeller specs.
Current Build Matrix
CI | .NET | Postgres | plv8 | Serializer |
---|---|---|---|---|
GitHub Actions | 8 | 12.8 | :white_check_mark: | STJ |
GitHub Actions | 8 | 15-alpine | :x: | Newtonsoft |
GitHub Actions | 7 | 12.8 | :white_check_mark: | JSON.NET |
GitHub Actions | 7 | latest | :x: | STJ |
Azure Pipelines | 6 | 12.8 | :white_check_mark: | JSON.NET |
Azure Pipelines | 6 | 12.8 | :white_check_mark: | STJ |
Azure Pipelines | 6 | 15-alpine | :x: | STJ |
Azure Pipelines | 6 | latest | :x: | Newtonsoft |
Documentation
All the documentation is written in Markdown and the docs are published as a static site hosted in Netlify. v4.x and v3.x use different documentation tools hence are detailed below in separate sub-sections.
v4.x and above
VitePress is used as documentation tool. Along with this, MarkdownSnippets is used for adding code snippets to docs from source code and Algolia DocSearch is used for searching the docs via the search box.
The documentation content is the Markdown files in the /docs
directory directly under the project root. To run the docs locally use npm run docs
with auto-refresh on any changes.
To add code samples/snippets from the tests in docs, follow the steps below:
Use C# named regions to mark a code block as described in the sample below
#region sample_my_snippet
// code sample/snippet
// ...
#endregion
All code snippet identifier starts with sample_
as a convention to clearly identify that the region block corresponds to a sample code/snippet used in docs. Recommend to use snake case for the identifiers with words in lower case.
Use the below to include the code snippet in a docs page
<!-- snippet: sample_my_snippet --> <!-- endSnippet -->
Note that when you run the docs locally, the above placeholder block in the Markdown file will get updated inline with the actual code snippet from the source code. Please commit the changes with the auto-generated inline code snippet as-is after you preview the docs page. This helps with easier change tracking when you send PR's.
Few gotchas:
- Any changes to the code snippets will need to done in the source code. Do not edit/update any of the auto-generated inline code snippet directly in the Markdown files.
- The latest snippet are always pulled into the docs while we publish the docs. Hence do not worry about the inline code snippet in Markdown file getting out of sync with the snippet in source code.
v3.x
stdocs is used as documentation tool. The documentation content is the markdown files in the /documentation
directory directly under the project root. Any updates to v3.x docs will need to done in 3.14 branch. To run the documentation website locally with auto-refresh, refer to the build commands section above.
If you wish to insert code samples/snippet to a documentation page from the tests, wrap the code you wish to insert with
// SAMPLE: name-of-sample
and // ENDSAMPLE
.
Then to insert that code to the documentation, add <[sample:name-of-sample]>
.
Note: content is published to the
gh-pages
branch of this repository. Refer to build commands section to lookup the command for publishing docs.
License
Copyright © Jeremy D. Miller, Babu Annamalai, Oskar Dudycz, Joona-Pekka Kokko and contributors.
Marten is provided as-is under the MIT license. For more information see LICENSE.
Code of Conduct
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
Top Related Projects
EventStoreDB, the event-native database. Designed for Event Sourcing, Event-Driven, and Microservices architectures
A persistence agnostic Event Store for .NET
EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
Npgsql is the .NET data provider for PostgreSQL.
Canonical actor model implementation for .NET with local + distributed actors in C# and F#.
Simple, unambitious mediator implementation in .NET
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot