Introduction

Click this link to watch an introductory video on Marten.

What is Marten?

Marten is a .NET library that allows developers to use the Postgresql database as both a document database and a fully-featured event store -- with the document features serving as the out-of-the-box mechanism for projected "read side" views of your events. There is absolutely nothing else to install or run, outside of the Nuget package and Postgresql itself. Marten was made possible by the unique JSONB support first introduced in Postgresql 9.4.

Marten was originally built to replace RavenDB inside a very large web application that was suffering stability and performance issues. The project name Marten came from a quick Google search one day for "what are the natural predators of ravens?" -- which led to us to use the marten as our project codename and avatar.

A Marten

The Marten project was publicly announced in late 2015 and quickly gained a solid community of interested developers. An event sourcing feature set was added, which proved popular with our users. Marten first went into a production system in 2016 and has been going strong ever since. The v4 release in 2021 marks a massive overhaul of Marten's internals, and introduces new functionality requested by our users to better position Marten for the future.

.NET Version Compatibility

Marten aligns with the .NET Core Support Lifecycle to determine platform compatibility.

Marten v4 targets netstandard2.0 & net5.0 and is compatible with .NET Core 3.1 & .NET 5+. .NET Core 2.1 may work but is out of support and thus untested.

.NET Framework support was dropped as part of the v4 release. If you require .NET Framework support, please use the latest Marten v3 release.

Nullable Reference Types

For enhanced developer ergonomics, Marten supports NRTs. For users of .NET 6 or later, this is automatically enabled in new projects. In previous versions of .NET, this can be opted-into via <Nullable>enable</Nullable> within your .csproj.

Marten Quick Start

Following the common .Net idiom, Marten supplies extension methods to quickly integrate Marten into any .Net application that uses the IServiceCollection abstractions to register IoC services.

In the ConfigureServices() method of your ASP.NET Core or Generic Host application, make a call to AddMarten() to register Marten services like so:

public void ConfigureServices(IServiceCollection services)
{
    // This is the absolute, simplest way to integrate Marten into your
    // .Net Core application with Marten's default configuration
    services.AddMarten(options =>
    {
        // Establish the connection string to your Marten database
        options.Connection(Configuration.GetConnectionString("Marten"));

        // If we're running in development mode, let Marten just take care
        // of all necessary schema building and patching behind the scenes
        if (Environment.IsDevelopment())
        {
            options.AutoCreateSchemaObjects = AutoCreate.All;
        }
    });
}
// and other methods we don't care about right now...

snippet source | anchor

See Bootstrapping with HostBuilder for more information and options about this integration.

Also see the blog post Marten, the Generic Host Builder in .Net Core, and why this could be the golden age for OSS in .Net for more background about how Marten is fully embracing the generic host in .Net.

INFO

The complete ASP.NET Core sample project is available in the Marten codebase

Working with Documents

Now, for your first document type, we'll represent the users in our system:

public class User
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool Internal { get; set; }
    public string UserName { get; set; }
    public string Department { get; set; }
}

snippet source | anchor

For more information on document identity, see identity.

And now that we've got a PostgreSQL schema and an IDocumentStore variable called store, let's start persisting and loading user documents:

// Open a session for querying, loading, and
// updating documents
using (var session = store.LightweightSession())
{
    var user = new User { FirstName = "Han", LastName = "Solo" };
    session.Store(user);

    await session.SaveChangesAsync();
}

// Open a session for querying, loading, and
// updating documents with a backing "Identity Map"
using (var session = store.QuerySession())
{
    var existing = await session
        .Query<User>()
        .SingleAsync(x => x.FirstName == "Han" && x.LastName == "Solo");
}

snippet source | anchor

We can use our document store to create a new IQuerySession object just for querying or loading documents from the database:

using (var session = store.QuerySession())
{
    var internalUsers = session
        .Query<User>().Where(x => x.Internal).ToArray();
}

snippet source | anchor

For more information on the query support within Marten, check document querying

There is a lot more capabilities than what we're showing here, so head on over to the table of contents on the sidebar to see what else Marten offers.

Working with Events

Please check Event Store quick start