每个租户的数据库 - 一步一步的例子来证实我的想法

时间:2017-11-17 11:11:39

标签: aspnetboilerplate

我只需要确认我正在努力实现这一方面的正确轨道。

第1步:为每个租户创建一个新的上下文,例如

public class TenantOneContext : AbpZeroDbContext<Tenant, Role, User, TenantOneContext{


  public DbSet<MyModel1> MyModel1S { get; set; }
  public DbSet<MyModel1> MyModel2S { get; set; }

第2步: 我假设使用命名约定,存在的每个上下文,都有一个关联的[contextname]配置器,例如

public static class TenantOneContextConfigurer
    {
        public static void Configure(DbContextOptionsBuilder<TenantOneContext> builder, string connectionString)
        {
            builder.UseSqlServer(connectionString);
        }

        public static void Configure(DbContextOptionsBuilder<TenantOneContext> builder, DbConnection connection)
        {
            builder.UseSqlServer(connection);
        }

第3步:为每个租户上下文创建新的[contextname]工厂,例如

 public class TenantOneContextFactory : IDesignTimeDbContextFactory<TenantOneContext>

在继承AbpModule的模块中 - 添加一些代码来执行自定义连接字符串解析,例如

public class MyAppEntityFrameworkModule : AbpModule { 

  //new code to  resolve conn strings / tennant
   Configuration.ReplaceService<IConnectionStringResolver, DbPerTenantConnectionStringResolver>(DependencyLifeStyle.Transient);

我认为就是这样 - 但寻找确认......: - )

1 个答案:

答案 0 :(得分:3)

对于每个租户,您可能不需要不同的DbContext,只需要不同的连接。

  

如果是这样,是否有映射conn字符串的命名约定?或者映射在哪里发生?

连接字符串存储在Tenant实体:

public const int MaxConnectionStringLength = 1024;

[StringLength(MaxConnectionStringLength)]
public virtual string ConnectionString { get; set; }

映射发生在DbPerTenantConnectionStringResolver

if (args.TenantId == null)
{
    // Requested for host
    return base.GetNameOrConnectionString(args);
}

var tenantCacheItem = _tenantCache.Get(args.TenantId.Value);
if (tenantCacheItem.ConnectionString.IsNullOrEmpty())
{
    // Tenant has no dedicated database
    return base.GetNameOrConnectionString(args);
}

return tenantCacheItem.ConnectionString;