Fork me on GitHub

Multi-Tenancy with Basic Store Operations Edit on GitHub


Once configured for multi-tenancy, Marten exposes it via sessions (IQuerySession, IDocumentSession) scoped to specific tenants, as well as various overloads to saving operations that accept a tenant identifier.

Scoping Sessions to Tenancy

The following sample demonstrates scoping a document session to tenancy idenfitied as tenant1. With multi-tenancy enabled, the persisted User objects are then associated with the tenancy of the session.


// Write some User documents to tenant "tenant1"
using (var session = store.OpenSession("tenant1"))
{
    session.Store(new User{UserName = "Bill"});
    session.Store(new User{UserName = "Lindsey"});
    session.SaveChanges();
}

As with storing, the load operations respect tenancy of the session.


// When you query for data from the "tenant1" tenant,
// you only get data for that tenant
using (var query = store.QuerySession("tenant1"))
{
    query.Query<User>()
        .Select(x => x.UserName)
        .ToList()
        .ShouldHaveTheSameElementsAs("Bill", "Lindsey");
}

Lastly, unlike reading operations, IDocumentSession.Store offers an overload to explicitly pass in a tenant identifier, bypassing any tenancy associated with the session. Similar overload for tenancy exists for IDocumentStore.BulkInsert.

Default Tenancy

With multi-tenancy enabled, Marten associates each record with a tenancy. If no explicit tenancy is specified, either via policies, mappings, scoped sessions or overloads, Marten will default to Tenancy.DefaultTenantId with a constant value of *DEFAULT*.

The following sample demonstrates peristing two User objects under default tenancy, then querying them back in a session scoped to Green and Red tenancies.


var greens = Target.GenerateRandomData(10).ToArray();
var reds = Target.GenerateRandomData(11).ToArray();

theStore.BulkInsert("Green", greens);
theStore.BulkInsert("Red", reds);

var user1 = new User {UserName = "Frank"};
var user2 = new User {UserName = "Bill"};

theStore.BulkInsert(new User[]{user1, user2});

using (var green = theStore.QuerySession("Green"))
{
    green.Query<User>().Count().ShouldBe(2);
    green.Query<Target>().Count().ShouldBe(10);
}

using (var red = theStore.QuerySession("Red"))
{
    red.Query<User>().Count().ShouldBe(2);
    red.Query<Target>().Count().ShouldBe(11);
}