Table of Contents

Multi-tenancy

The code here shows how to handle multiple tenants in a single database.

Tip

To use a different database per tenant, see this example instead. Its DbContext dynamically sets the connection string per request. This requires the database structure to be identical for all tenants.

The essence of implementing multi-tenancy within a single database is instructing Entity Framework Core to add implicit filters when entities are queried. See the usage of HasQueryFilter in the DbContext class. It injects an ITenantProvider to determine the active tenant for the current HTTP request.

Note

For simplicity, this example uses a route parameter to indicate the active tenant. Provide your own ITenantProvider to determine the tenant from somewhere else, such as the incoming OAuth token.

The generic MultiTenantResourceService transparently sets the tenant ID when creating a new resource. Furthermore, it performs extra queries to ensure relationship changes apply to the current tenant, and to produce better error messages.

While MultiTenantResourceService is used for both resource types, only the WebShop resource type implements IHasTenant. The related resource type WebProduct does not. Because the products table has a foreign key to the (tenant-specific) shop it belongs to, it doesn't need a TenantId column. When a JSON:API request for web products executes, the HasQueryFilter in the DbContext ensures that only products belonging to the tenant-specific shop are returned.