租户实现方式
This commit is contained in:
parent
00d975575c
commit
e5f5fefc5a
93
notes/helloshop/multi-tenancy.md
Normal file
93
notes/helloshop/multi-tenancy.md
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# 多租户应用程序设计
|
||||||
|
|
||||||
|
## 什么是多租户应用程序
|
||||||
|
|
||||||
|
多租户应用程序是一种软件架构设计,允许单个实例的软件服务多个客户,每个客户被称为一个租户,租户之间的数据自动隔离的,租户之间的数据不会相互影响。
|
||||||
|
|
||||||
|
零度编程官网搜索「多租户」查看多租户设计视频教程。
|
||||||
|
|
||||||
|
## 单表多字段隔离租户数据
|
||||||
|
|
||||||
|
单表多租户设计是指在一个表中存储多个租户的数据,通过在表中增加一个租户 TenantId 字段来区分不同租户的数据。
|
||||||
|
|
||||||
|
### 多租户数据查询
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class FieldIsolationServiceDbContext(DbContextOptions<FieldIsolationServiceDbContext> options, ICurrentTenant currentTenant) : DbContext(options)
|
||||||
|
{
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<Product>().Property(p => p.Name).HasMaxLength(32);
|
||||||
|
|
||||||
|
foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
|
||||||
|
{
|
||||||
|
if (entityType.ClrType.IsAssignableTo(typeof(IMultiTenant)))
|
||||||
|
{
|
||||||
|
modelBuilder.Entity(entityType.ClrType).AddQueryFilter<IMultiTenant>(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<EntityEntry<IMultiTenant>> multiTenancyEntries = dbContext.ChangeTracker.Entries<IMultiTenant>().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。
|
||||||
|
|
Loading…
Reference in New Issue
Block a user