多租户解析与Demo

在构建SaaS应用时,多租户架构的设计至关重要,它直接影响到用户如何与网站交互。

引言

多租户架构的数据库实现策略通常分为三种:

  1. 单一数据库模式:通过在每条数据中添加租户ID来区分不同租户的数据。
  2. 独立数据库模式:为每个租户提供独立的数据库,实现数据的完全隔离。
  3. 混合模式:基础数据存放于共享表中,而业务数据则根据租户分库存储。

无论采用哪种策略,识别当前租户身份是查询数据库的前提。

识别租户的方法多样:

  1. 基于域名或子域名:适用于所有场景,但需要域名和DNS服务支持。
  2. 基于用户ID:适用于单一数据库和混合模式,将租户信息存储在前端的cookie或header中,方便查询。

以下示例展示了一个简单的实现,未涉及复杂业务逻辑,主要功能如下:

  • 用户通过不同域名访问系统。
  • 后台接收HTTP请求中的域名并进行解析。
  • 查询租户数据库,返回租户名称。

项目结构

创建解决方案,并在其中添加三个项目:

  • try_MultiTenantApi:Web API项目,作为启动项目,包含租户的Service和IService。
  • MultiTenantApi.Models:类库项目,存放租户对象模型。
  • MultiTenantApi.Data:数据层项目,使用Entity Framework Core(EF Core),包含DbContext和迁移文件。
项目结构图

实体定义

MultiTenantApi.Models中新增实体Tenant

public class Tenant
{
    public int Id { get; set; }
    public string Identifier { get; set; } // 租户标识符,例如域名
    public string Name { get; set; }
    public string ConnectionString { get; set; } // 每个租户的独立数据库连接字符串
}

数据层配置

MultiTenantApi.Data中,引入必要的NuGet包,确保与项目.NET版本相匹配。

引入NuGet包

这些包包括:

  1. Microsoft.EntityFrameworkCore:提供ORM功能,支持多种数据库。
  2. Microsoft.EntityFrameworkCore.Design:提供设计时组件,管理数据库迁移。
  3. Microsoft.EntityFrameworkCore.Proxies:提供延迟加载代理,优化性能。
  4. Microsoft.EntityFrameworkCore.SqlServer:为SQL Server提供数据库提供程序。
  5. Microsoft.EntityFrameworkCore.Tools:提供EF Core工具,便于管理和使用。

数据上下文

新增数据上下文ApplicationDbContext

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions options)
    : base(options)
    {
    }
    public DbSet Tenants { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity().HasData(
            new Tenant { Id = 1, Identifier = "tenant1", Name = "Tenant 1", ConnectionString = "Server=(localdb)\\mssqllocaldb;Database=TenantDb1;Trusted_Connection=True;" },
            new Tenant { Id = 2, Identifier = "tenant2", Name = "Tenant 2", ConnectionString = "Server=(localdb)\\mssqllocaldb;Database=TenantDb2;Trusted_Connection=True;" }
        );
    }
}

注意:实际应用中需根据实际情况调整数据库连接字符串。

服务层

try_MultiTenantApi中引入NuGet包,并新建类TenantService

public interface ITenantService
{
    Task GetTenantByIdentifierAsync(string identifier);
}

public class TenantService : ITenantService
{
    private readonly ApplicationDbContext _context;

    public TenantService(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task GetTenantByIdentifierAsync(string identifier)
    {
        return await _context.Tenants.FirstOrDefaultAsync(t => t.Identifier == identifier);
    }
}

中间件

新建中间件TenantMiddleware,用于解析每个请求中的租户信息:

```java
namespace try_MultiTenantApi
{
public class TenantMiddleware
{
private readonly RequestDelegate _next;

    public TenantMiddleware(RequestDelegate next)
    {
        _next
版权声明:程序员胖胖胖虎阿 发表于 2024年12月26日 上午6:53。
转载请注明:多租户解析与Demo | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...