From e5f5fefc5a77301471073ccce4a85778e1cfbdd4 Mon Sep 17 00:00:00 2001 From: hello Date: Wed, 22 May 2024 13:14:20 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=9F=E6=88=B7=E5=AE=9E=E7=8E=B0=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/helloshop/multi-tenancy.md | 93 ++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 notes/helloshop/multi-tenancy.md diff --git a/notes/helloshop/multi-tenancy.md b/notes/helloshop/multi-tenancy.md new file mode 100644 index 0000000..45beb51 --- /dev/null +++ b/notes/helloshop/multi-tenancy.md @@ -0,0 +1,93 @@ +# 多租户应用程序设计 + +## 什么是多租户应用程序 + +多租户应用程序是一种软件架构设计,允许单个实例的软件服务多个客户,每个客户被称为一个租户,租户之间的数据自动隔离的,租户之间的数据不会相互影响。 + +零度编程官网搜索「多租户」查看多租户设计视频教程。 + +## 单表多字段隔离租户数据 + +单表多租户设计是指在一个表中存储多个租户的数据,通过在表中增加一个租户 TenantId 字段来区分不同租户的数据。 + +### 多租户数据查询 + +```csharp +public class FieldIsolationServiceDbContext(DbContextOptions options, ICurrentTenant currentTenant) : DbContext(options) +{ + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().Property(p => p.Name).HasMaxLength(32); + + foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes()) + { + if (entityType.ClrType.IsAssignableTo(typeof(IMultiTenant))) + { + modelBuilder.Entity(entityType.ClrType).AddQueryFilter(e => e.TenantId == currentTenant.TenantId); + } + } + + base.OnModelCreating(modelBuilder); + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.AddInterceptors(new TenantSaveChangesInterceptor(currentTenant)); + + base.OnConfiguring(optionsBuilder); + } +} +``` + +### 保存数据时自动设置租户编号 + +```csharp +private void MultiTenancyTracking(DbContext dbContext) +{ + IEnumerable> multiTenancyEntries = dbContext.ChangeTracker.Entries().Where(entry => entry.State == EntityState.Added || entry.State == EntityState.Modified); + + multiTenancyEntries?.ToList().ForEach(entityEntry => + { + entityEntry.Entity.TenantId ??= currentTenant.TenantId; + }); +} +``` + +## 多数据库隔离租户数据 + +多数据库多租户设计是指为每个租户创建一个独立的数据库,通过数据库连接字符串来区分不同租户的数据。 + + +```csharp + +protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) +{ + if (currentTenant.TenantId != null) + { + string? connectionString = configuration.GetConnectionString(currentTenant.TenantId); + + optionsBuilder.UseNpgsql(connectionString); + } + + base.OnConfiguring(optionsBuilder); +} +``` + +## 基于 Schema 的多租户设计 + +基于 Schema 的多租户设计是指为每个租户创建一个独立的 Schema,通过 Schema 来区分不同租户的数据。 + +```csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) +{ + if (currentTenant.TenantId != null) + { + modelBuilder.HasDefaultSchema(currentTenant.TenantId); + } + + base.OnModelCreating(modelBuilder); +} +``` + +目前 EF Core 不支持在迁移时自动创建 Schema,需要手动创建 Schema。 +