目录
SAAS 和多租户
SaaS(软件及服务)区别于其他应用程序的主要特征就是能够使客户在使用应用程序时按照使用量付费。他们不需要为软件购买许可,也不需要安装、托管和管理它。这方面的操作全部由提供 SaaS 软件的组织负责。
多租户是实现 SaaS 的关键因素, 它可以让多个企业或组织用户共用相同的系统或程序组件, 同时不会破坏这些组织的数据的安全性, 确保各组织间数据的隔离性.
多租户数据隔离方案
-     单数据库 如果软件系统仅部署一个实例,并且所有租户的数据都是存放在一个数据库里面的,那么可以通过一个 TenantId (租户 Id) 来进行数据隔离。那么当我们执行 SELECT 操作的时候就会附加上当前登录用户租户 Id 作为过滤条件,那么查出来的数据也仅仅是当前租户的数据,而不会查询到其他租户的数据。 这是共享程度最高、隔离级别最低的模式。需要在设计开发时加大对安全的开发量。 
-     多数据库 为每一个租户提供一个单独的数据库,在用户登录的时候根据用户对应的租户 ID,从一个数据库连接映射表获取到当前租户对应的数据库连接字符串,并且在查询数据与写入数据的时候,不同租户操作的数据库是不一样的。 这种方案的用户数据隔离级别最高,安全性最好,但维护和购置成本较高. 
也有一种介于两者之间的方案: 共享数据库,独立 Schema. 但实际应用的应该不多.
使用 EF Core 简单实现多租户
租户 Id 的获取可以采用两种方法:
- 根据登录用户获取. 作为登录用户的附加信息, 比如把租户 Id 放到Json Web Token里面或者根据用户 Id 去数据库里取对应的租户 Id.
- 根据企业或组织用户的Host获取. 部署的时候会给每个企业或组织分配一个单独的Host, 并在数据库里维护着一个租户 Id 和 Host 的映射表. 查询的时候根据 Host 去取对应的租户 Id.
在框架编写的时候, 我们最好能把对租户 Id 的处理(查询时候的过滤和保存时候的赋值) 放在数据访问的最底层自动实现. 从而让业务逻辑的开发人员尽量少的去关注租户 Id, 而是像开发普通应用一样去开发多租户应用.
EF Core 在2.0版本引入了"模型级别查询筛选器”的新功能, 此功能可以帮助开发人员方便实现软删除和多租户等功能.
单数据库实现
下面使用 EF Core 简单实现一个单数据库多租户的 Demo. 采用 Host 获取租户 Id.
-     创建 Tenant 实体类和 TenantsContext, 用于存储租户 Id 和 Host 的映射, 并根据 Host 从数据库里获取 Id. public class Tenant { public Guid Id { get; set; } public string Name { get; set; } public string Host { get; set; } } public class TenantConfiguration : IEntityTypeConfiguration<Tenant> { public void Configure(EntityTypeBuilder<Tenant> builder) { builder.HasKey(t => t.Id); builder.Property(t => t.Name).HasMaxLength(100).IsRequired(); builder.Property(t => t.Host).HasMaxLength(100).IsRequired(); builder.HasData( new Tenant { Id = Guid.Parse("B992D195-56CE-49BF-BFDD-4145BA9A0C13"), Name = "Customer A", Host = "localhost:5200" }, new Tenant { Id = Guid.Parse("F55AE0C8-4573-4A0A-9EF9-32F66A828D0E"), Name = "Customer B", Host = "localhost:5300" }); } }public class TenantsContext : DbContext { public TenantsContext(DbContextOptions<TenantsContext> options) : base(options) { } private DbSet<Tenant> Tenants { get; set; }
