Multi-tenant ASP.NET Core 7 - Defensive database context
gpeipman
3,371 views
Open Source Your Knowledge, Become a Contributor
Technology knowledge has to be shared and made accessible for free. Join the movement.
Defensive database context
To make sure that data from different tenants doesn't get mixed in multi-tenant application we can add some defensive behaviour to multi-tenant database context to build additional safety net for application developers.
The following demonstrates defensive database context and it uses the following classes:
- ITenantProvider - interface for tenant providers,
- DummyTenantProvider - tenant provider for demo purposes,
- BaseEntity - base class for all entities,
- Person - sample entity type for this demo,
- CrossTenantUpdateException - exception type for operations that use data from multiple tenants,
- SampleDbContext - defensive database context.
The sample below creates new instance of database context, adds two instances of Person entities that belong to different tenants and then saves changes. If cross-tenant operation exception is thrown then tenant ID-s involved to incident are written out.
Click to run the .NET Core Web app.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace EFDefensive
{
public interface ITenantProvider
{
Guid GetTenantId();
}
public class DummyTenantProvider : ITenantProvider
{
public static Guid Tenant1Id = Guid.Parse("51aab199-1482-4f0d-8ff1-5ca0e7bc525a");
public static Guid Tenant2Id = Guid.Parse("ae4e21fa-57cb-4733-b971-fdd14c4c667e");
public Guid GetTenantId()
{
return Tenant1Id;
}
}
public abstract class BaseEntity
{
[Key]
public int Id { get; set; }
public Guid TenantId { get; set; }
}
public class Person : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class CrossTenantUpdateException : ApplicationException
{
public IList<Guid> TenantIds { get; private set; }
public CrossTenantUpdateException(IList<Guid> tenantIds)
{
TenantIds = tenantIds;
}
}
public class SampleDbContext : DbContext
{
Enter to Rename, Shift+Enter to Preview
References
- Defensive database context for multi-tenant ASP.NET Core applications (Gunnar Peipman)
- Implementing tenant providers on ASP.NET Core (Gunnar Peipman)
Suggested playgrounds
Open Source Your Knowledge: become a Contributor and help others learn. Create New Content