Marten for C# (.NET): Complete Guide to Document DB and Event Store on PostgreSQL
Marten is a powerful .NET library that turns PostgreSQL into a hybrid data store, combining the capabilities of a Document Database and an Event Store. Built by the JasperFx team, it lets developers work with PostgreSQL like a NoSQL system while keeping all the benefits of a relational database.
Why use Marten? Modern development often needs the flexibility of document databases (like MongoDB) for storing complex, semi-structured data, along with the reliability and transactional support of relational databases. Marten solves this by providing a LINQ provider for working with JSON documents stored in PostgreSQL, plus a full-featured Event Store for implementing Event Sourcing and CQRS patterns. This is especially useful in microservice architectures, audit systems, financial applications, and any project requiring both schema flexibility and strong consistency.
The library is actively maintained and used in production. It integrates with ASP.NET Core and Entity Framework Core (when needed), offering a rich API for data operations. Marten automatically creates and updates database schemas, supports migrations, indexes, and even full-text search. This makes it an excellent choice for .NET developers who want to leverage PostgreSQL's power without writing complex SQL.
Installation
Install Marten via NuGet Package Manager. Run one of the following commands:
dotnet add package Marten
Or via Package Manager Console:
Install-Package Marten
No additional packages are needed for the Event Store — everything is included in the main package. We also recommend installing Marten.AspNetCore for ASP.NET Core integration:
dotnet add package Marten.AspNetCore
Quick Start
A minimal working example includes setting up a PostgreSQL connection, defining a document, and performing CRUD operations.
using Marten;
using System;
using System.Threading.Tasks;
// 1. Define a document
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
class Program
{
static async Task Main(string[] args)
{
// 2. Configure DocumentStore
var store = DocumentStore.For(options =>
{
options.Connection("Host=localhost;Database=marten_db;Username=postgres;Password=password");
options.AutoCreateSchemaObjects = AutoCreate.All; // Auto-create tables
});
// 3. Open a session
using var session = store.LightweightSession();
// 4. Create a document
var user = new User
{
Id = Guid.NewGuid(),
Name = "John Doe",
Age = 30,
Email = "john@example.com"
};
session.Store(user);
await session.SaveChangesAsync();
// 5. Load document by ID
var loadedUser = await session.LoadAsync<User>(user.Id);
Console.WriteLine($"Loaded user: {loadedUser.Name}, age: {loadedUser.Age}");
// 6. Update the document
loadedUser.Age = 31;
session.Store(loadedUser);
await session.SaveChangesAsync();
// 7. Delete the document
session.Delete(loadedUser);
await session.SaveChangesAsync();
Console.WriteLine("Done!");
}
}
This example demonstrates basic operations: create, read, update, and delete a document. Ma
Also in library
TypeStack/routing-controllers for TypeScript: Complete Guide with Examples
Working with Excel in Java: Apache POI and Alternatives
Data Validation in Rust: Libraries and Approaches for Reliable Code