Skip to content

Multi Tenancy

Christopher Davis edited this page Jan 8, 2020 · 2 revisions

Another built-in feature is the ability to add multi-tenant functionality. This feature allows for the design of applications that may be used by multiple, independent users with total data separation. This contrasts with multi-instance software which requires a separate installation or database. nHydrate implements a shared schema model with each tenant having an assigned database owning specific data. A simple explanation can be found here.

A good example of a multi-tenant system is a banking website. Each user logs in is a tenant and has access to only his own data. It is very important that there be no data bleed. No user can access any other user’s data. This is handled via the connection string. By making this context level functionality there is no way for a developer to accidentally or intentionally access data from another tenant.

In this example, the data context is created with two different connection strings. There is no need for a Where statement in LINQ. Even calling ToList to get all objects will only pull back data for a single tenant. A developer cannot accidently forget to add a tenant qualifier. It is baked into the framework.

//Connect as tenant 1
var connectionString = ConnectionUtil.TenantConnection(1);
using (var context = new MyEntities(connectionString))
{
    var objects = context.Data.ToList();
}

//Connect as tenant 2
connectionString = ConnectionUtil.TenantConnection(2);
using (var context = new MyEntities(connectionString))
{
    var objects = context.Data.ToList();
}

nHydrate implements this functionality by modifying the Entity Framework mapping files to route all queries to managed, internal views that pull back data only for the logged-in database user. In this way, there is no way to pull back data not associated with the correct tenant using Entity Framework. This is an implementation of row level ownership. The permission functionality is completely transparent to the API.

To setup a multi tenant model, simply define a model as usual. On tables that are to be marked for tenant functionality, set the IsTenant property to true. That is the only setting to change. The connection string used to insert the data is the same connection string used to query the data. The only external requirement is that a database user be created for each tenant. The database user is used in the tenant connection string.