Database per tenant - a step by step example to confirm my thinking

旧时模样 提交于 2019-12-23 04:47:34

问题


I just need confirmation I'm on the right track with this aspect I'm trying to implement.

Step 1: for each tenant create a new context eg

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


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

Step 2: I assume using a naming convention, that each context that exists, there is an associated [contextname]Configurer eg

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);
        }

Step 3: create new [contextname]Factory for each tenant-context eg

 public class TenantOneContextFactory : IDesignTimeDbContextFactory<TenantOneContext>

In the module that inherits AbpModule - add some code to do custom connection string resolving eg

public class MyAppEntityFrameworkModule : AbpModule { 

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

I think that is it - but looking for confirmation...:-)


回答1:


You probably don't need a different DbContext for each tenant, just a different connection.

if so, is there a naming convention for mapping the conn strings ? or where does the mapping take place?

The connection string is stored in Tenant entity:

public const int MaxConnectionStringLength = 1024;

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

The mapping takes places in 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;


来源:https://stackoverflow.com/questions/47349344/database-per-tenant-a-step-by-step-example-to-confirm-my-thinking

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!