# Fast Document Database In .NET With Marten

> Did you know you can turn PostgreSQL into a fully-fledged Document database? Marten is a .NET library that lets you use PostgreSQL as both a document database and a fully-featured event store, relying on JSONB. Let me show you the basics of working with Marten.

Published: 2022-12-17. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/fast-document-database-in-net-with-marten

Marten is a .NET library that turns a PostgreSQL database into a document store and an event store, using the `JSONB` support available since PostgreSQL 9.4.
You install the NuGet package, call `AddMarten` with a connection string, and store objects as JSON documents.
Queries work with LINQ or plain SQL.

Did you know you can turn **PostgreSQL** into a fully-fledged **Document database**?

**Marten** is a **.NET** library that allows developers to use the **PostgreSQL**
database as both a **document database** and a fully-featured **event store**.

You don't need to install anything else to be able to use **PostgreSQL**
as a **document database**, outside of the Nuget package. **Marten** relies
on the **JSONB** support available since **PostgreSQL** 9.4.

In this week's newsletter, I want to introduce you to the basics of working
with **Marten** and show you how easy it is to get started.

Let's dive in.

## Installing And Configuring Marten

What are you going to need to start using **PostgreSQL** as a **Document datbase**?

Other than a running instance of **PostgreSQL**, of course, you will need
to install the **Marten** Nuget package:

```csharp
dotnet add package Marten
```

**Marten** can build the required database schema and necessary tables on the fly,
and I suggest using this approach in development.
For a production environment, you definitely want to apply schema
changes on your own with migration scripts.

To register **Marten** with dependency injection, you need to call the `AddMarten`
method.

Here's an example **Marten** configuration inside of a **.NET 7** application:

```csharp
builder.Services.AddMarten(options =>
{
    options.Connection(builder.Configuration.GetConnectionString("Marten"));
});
```

This will register a few services with dependency injection:

- `IDocumentStore` - used to create sessions, generate schema migrations, and do bulk inserts
- `IDocumentSession` - used for read and write operations
- `IQuerySession` - used for read operations

Let's see how we can work with documents using **Marten**.

## Storing Documents With Marten

Storing documents in the database is very straightforward. You need to create
a new `DocumentStore` instance, and open an `IDocumentSession` which exposes
methods for storing and persisting documents.

Let's see how we can store a `Product` document:

```csharp
var store = DocumentStore.For("Connection string to PostgreSQL");

using var session = store.OpenSession();

var product = new Product
{
    Name = "C# 11 and .NET 7 - Modern Cross-Platform Fundamentals",
    Price = 46.87
};

session.Store(product);

await session.SaveChangesAsync();
```

We're creating a new `DocumentStore` instance which we use to open
a session to **PostgreSQL**. And then we just call `Store` and pass in
the `Product` instance. Note that **Marten** will populate the
`Product.Id` at this point. **Marten** can populate keys of `Guid`,
`int`, `long`, and other data types. It uses the HiLo algorithm
for numeric keys. Finally, when we call `SaveChangesAsync` the
`Product` is serialized into **JSON** and persisted as a document.

An important thing to be aware of is that the `IDocumentSession`
created by `OpenSession` doesn't track changes on the entities automatically.
You need to create a session with dirty checking enabled by
calling `DirtyTrackedSession` on the `DocumentStore` to enable
automatic change detection.

## Querying Documents With Marten

**Marten** has rich support for querying documents in the database.
You can write and execute queries using **LINQ**, which you are
familiar with if you worked with **EF Core**. And you can also
write and execute **SQL** queries, because it's still a **PostgreSQL**
database underneath.

Here's an example query to return products that have a higher price
than the one which is specified:

```csharp
var store = DocumentStore.For("Connection string to PostgreSQL");

using var session = store.QuerySession();

var products = session.Query<Product>().Where(p => p.Price > 9.99).ToList();
```

**Marten** also has support for:

- Including related documents
- Batched queries
- Paging
- Full text search

## Advanced Options With Marten

**Marten** can utilize the full capabilities **PostgreSQL** has to offer,
notably transactions and indexing. **Marten** sessions are transactional
by default, either all of the documents are persisted together or
none of them are. And you can configure indexes on your documents
for faster queries.

**Marten** isn't just a **document database** on top of **PostgreSQL**!

You have fully-fledged support for [**event sourcing**](https://milanjovanovic.tech/blog/introduction-to-event-sourcing-for-net-developers) with **Marten**,
as well as projections. This makes it a perfect choice for
implementing **CQRS**. But this is a topic for a separate newsletter.

## Closing Thoughts

I'm absolutely amazed with [Marten](https://martendb.io/) and what it has to offer.
And **PostgreSQL** is also my favorite database, so it's like a match
made in heaven. I don't get too excited about learning new
technologies, but **Marten** has been an endless source
of joy this past week.

I still need to explore a few more topics before I can consider it
for production use:

- Schema migrations
- Relationships and foreign keys
- Advanced configuration options

Considering that **PostgreSQL** is cheaper than most **document databases**,
I think using **Marten** is an interesting alternative. And if you are
familiar with **SQL** databases, you can still use all of that knowledge.

---

## Frequently asked questions

### What is Marten in .NET?

Marten is a .NET library that lets you use PostgreSQL as both a document database and a fully-featured event store. It relies on the JSONB support available since PostgreSQL 9.4, so you only need the NuGet package and a running PostgreSQL instance.

### How do you configure Marten in a .NET application?

Install the Marten NuGet package and call AddMarten with your PostgreSQL connection string. This registers IDocumentStore for creating sessions, generating schema migrations, and bulk inserts, IDocumentSession for read and write operations, and IQuerySession for read operations.

### How do you store documents with Marten?

Open an IDocumentSession from a DocumentStore, call Store with your object, then SaveChangesAsync. Marten populates the document key (Guid, int, long, and other types, using the HiLo algorithm for numeric keys) and persists the object as a serialized JSON document.

### Does Marten track changes to documents automatically?

Not by default. A session created with OpenSession doesn't track changes on entities. Call DirtyTrackedSession on the DocumentStore to create a session with dirty checking enabled, which gives you automatic change detection.

### Can you query Marten documents with LINQ?

Yes. Marten supports LINQ queries, which feel familiar if you have worked with EF Core, and you can also write SQL queries because it is still a PostgreSQL database underneath. It supports including related documents, batched queries, paging, and full text search.

### Are Marten sessions transactional?

Yes. Marten sessions are transactional by default: either all of the documents are persisted together or none of them are. You can also configure indexes on your documents for faster queries, and Marten supports event sourcing with projections, making it a good fit for CQRS.
