Practical ASP.NET

ORM-Less Data Storage with Document Databases and Marten

Document databases are a form of NoSQL database that may store all of the information for a given object in a single instance in the database. Contrast this with relational databases that might store a given object across multiple tables in the database.

Marten is a .NET open source library that allows the easy storage, loading, updating and deleting of objects in an underlying document store. The underlying store that Marten is built on is the open source PostgreSQL database server.

Marten makes use of the advanced JSON capabilities of PostgreSQL to store .NET objects as JSON data.

Marten can improve developer productivity by not requiring complex schema changes as the application evolves, as can be the case with using a relational database. Marten also doesn't require the up-front definition of indexes for the .NET objects/JSON data that will be stored.

Getting Started
Marten can be installed into a Visual Studio project via the Marten NuGet package.

Once installed, Marten can talk to a PostgreSQL instance and store .NET objects.

The central point of communication between the application and Marten is a DocumentStore instance. This DocumentStore defines a connection to a PostgreSQL instance in addition to other Marten configuration options. Normally there's only going to be a single instance of the document store in the application. To create a DocumentStore instance, the static For method can be called and a connection string provided.

The actual work of storing, loading, updating and deleting documents is done in the context of a session. There are a number of different types of sessions and these can easily be created from a document store instance. For example, to create a session that allows documents in the database to be manipulated, the LightweightSession method can be called and it will return an IDocumentSession instance that can be used to work with documents. This code demonstrates the creation of a DocumentStore and a session:

DocumentStore store = DocumentStore.For(
  "host = localhost; database = RPGDatabase; password = g7qo84nck22i; username = postgres");

using (IDocumentSession session = store.LightweightSession())
{
  // Document manipulation code
}

Defining Documents
The .NET objects in the application are stored as documents by Marten. The basic requirement is that the .NET objects that are to be stored need an identity field or property. One way to define this is to follow a naming convention and name the property/field "Id." This code shows the definition of a Player class to represent a player in a role-playing game:

class Player
{
  public int Id { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public IList<Weapon> Weapons { get; set; } = new List<Weapon>();
}

internal class Weapon
{
  public string WeaponName { get; set; }
  public int WeaponDamage { get; set; }
}

The Player class also has a nested list of weapons that the player currently possesses.

Now instances of players can be stored in the session. Listing 1 shows the code required to store a new instance.

Listing 1: The Code Required to Store a New Instance
using (IDocumentSession session = store.LightweightSession())
{
  Player newPlayer = new Player
  {
    Name = "Krondure",
    Weapons =
    {
      new Weapon {WeaponName = "Sword", WeaponDamage = 42},
      new Weapon {WeaponName = "Axe", WeaponDamage = 230}
    }
  };
  // Add the object to the session
  session.Store(newPlayer);

  // Update database
  session.SaveChanges();
}

In the underlying PostgreSQL table, a new row will be written to the mt_doc_player table with a field containing the following document data:

{"Weapons":[{"WeaponDamage":42,"WeaponName":"Sword"},
  {"WeaponDamage":230,"WeaponName":"Axe"}],"Id":1,"Name":"Krondure"}

To update an existing document using an automatic change-tracking session, the following code could be used, which loads the player with an Id of 1, updates the name and then saves those changes:

// Create a session with auto-change-tracking
using (IDocumentSession session = store.DirtyTrackedSession())
{
  Player player = session.Load<Player>(1);

  player.Name = "Krondure the magnificent";
                
  session.SaveChanges();
}

To learn more about Marten, check out the GitHub documentation page.

About the Author

Jason Roberts is a Microsoft C# MVP with over 15 years experience. He writes a blog at http://dontcodetired.com, has produced numerous Pluralsight courses, and can be found on Twitter as @robertsjason.

comments powered by Disqus

Featured

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

  • VS Code Copilot Previews New GPT-4o AI Code Completion Model

    The 4o upgrade includes additional training on more than 275,000 high-quality public repositories in over 30 popular programming languages, said Microsoft-owned GitHub, which created the original "AI pair programmer" years ago.

  • Microsoft's Rust Embrace Continues with Azure SDK Beta

    "Rust's strong type system and ownership model help prevent common programming errors such as null pointer dereferencing and buffer overflows, leading to more secure and stable code."

  • Xcode IDE from Microsoft Archrival Apple Gets Copilot AI

    Just after expanding the reach of its Copilot AI coding assistant to the open-source Eclipse IDE, Microsoft showcased how it's going even further, providing details about a preview version for the Xcode IDE from archrival Apple.

Subscribe on YouTube

Upcoming Training Events