每个租户的数据库 - 一步一步的例子来证实我的想法
Database per tenant - a step by step example to confirm my thinking
我只需要确认我正在尝试实施的这方面是正确的。
步骤 1:为每个租户创建一个新的上下文,例如
public class TenantOneContext : AbpZeroDbContext<Tenant, Role, User, TenantOneContext{
public DbSet<MyModel1> MyModel1S { get; set; }
public DbSet<MyModel1> MyModel2S { get; set; }
步骤 2:
我假设使用命名约定,每个存在的上下文都有一个关联的 [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);
}
步骤 3:为每个租户上下文创建新的 [contextname]Factory 例如
public class TenantOneContextFactory : IDesignTimeDbContextFactory<TenantOneContext>
在继承AbpModule
的模块中-添加一些代码来进行自定义连接字符串解析,例如
public class MyAppEntityFrameworkModule : AbpModule {
//new code to resolve conn strings / tennant
Configuration.ReplaceService<IConnectionStringResolver, DbPerTenantConnectionStringResolver>(DependencyLifeStyle.Transient);
我想就是这样 - 但正在寻找确认...:-)
您可能不需要为每个租户使用不同的 DbContext
,只需要不同的连接。
if so, is there a naming convention for mapping the conn strings ? or where does the mapping take place?
连接字符串存储在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;
我只需要确认我正在尝试实施的这方面是正确的。
步骤 1:为每个租户创建一个新的上下文,例如
public class TenantOneContext : AbpZeroDbContext<Tenant, Role, User, TenantOneContext{
public DbSet<MyModel1> MyModel1S { get; set; }
public DbSet<MyModel1> MyModel2S { get; set; }
步骤 2: 我假设使用命名约定,每个存在的上下文都有一个关联的 [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);
}
步骤 3:为每个租户上下文创建新的 [contextname]Factory 例如
public class TenantOneContextFactory : IDesignTimeDbContextFactory<TenantOneContext>
在继承AbpModule
的模块中-添加一些代码来进行自定义连接字符串解析,例如
public class MyAppEntityFrameworkModule : AbpModule {
//new code to resolve conn strings / tennant
Configuration.ReplaceService<IConnectionStringResolver, DbPerTenantConnectionStringResolver>(DependencyLifeStyle.Transient);
我想就是这样 - 但正在寻找确认...:-)
您可能不需要为每个租户使用不同的 DbContext
,只需要不同的连接。
if so, is there a naming convention for mapping the conn strings ? or where does the mapping take place?
连接字符串存储在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;