多数据库的多租户与代码优先EF 6和ASP.Net MVC 4

本文关键字:EF ASP Net MVC 数据库 代码 多数据 | 更新日期: 2023-09-27 18:03:03

我正在构建一个SAAS应用程序,并计划每个客户端使用一个数据库。我使用Code First EF6与ASP。. Net MVC 4.

将有2个上下文,即MasterContext和TenantContext。用户将首先点击MasterContext来验证用户凭据并获取其租户配置。

基于获取的租户配置;TenantContext设置为特定于租户的数据库,用于租户CRUD操作。

多数据库的多租户与代码优先EF 6和ASP.Net MVC 4

这个想法是识别当前请求tenant_id并使用它来获取数据库配置并创建DbContext,就像下面的代码一样。

public AppDbContext : DbContext
{
    private const string _defaultCS = "default app connection string";
    public AppDbContext() : base(GetConnectionString())
    {
    }
    private string GetConnectionString()
    {
        return TenantContext.ConnectionString ?? _defaultCS;
    }
}
样本使用

public class StudentRepo
{
    public Student Get(Guid id)
    {
        using(var ctx = new AppDbContext())
        {
            return ctx.Students.FirstOrDefault(x=>x.Id == id);
        }
    }
}

将自动连接到已登录的租户数据库。

您可能需要将tenant_id存储在Auth cookie中,并在PostAuthenticate_Event之后读取它并存储在HttpContext.Current.Items

public static TenantContext
{
    public static Guid TenantId 
    { 
        get 
        { 
            return (Guid)HttpContext.Current.Items["__TenantID"];  
        }
    }
     public static string ConnectionString
     {
        get 
        { 
            return TenantConfigService.GetConnectionString(TenantId);  
        }
     }
}

在某些HTTP模块中Init方法

context.PostAuthenticateRequest += context_PostAuthenticateRequest; 
void context_PostAuthenticateRequest(object sender, EventArgs e)
{
    FormsIdentity identity = Thread.CurrentPrincipal.Identity as FormsIdentity;
    if (identity != null)
    {
        HttpContext.Current.Items["__TenantID"] = GetTenantIdFromTicket(identity.Ticket.UserData); // returns tenant_id as guid type
    }
}