feat: 添加租户初始化
This commit is contained in:
@@ -66,11 +66,20 @@ namespace Yi.Framework.SqlSugarCore.Abstractions
|
|||||||
public static string MasterTenantDbDefaultName = "Master";
|
public static string MasterTenantDbDefaultName = "Master";
|
||||||
public static string TenantDbDefaultName = "Default";
|
public static string TenantDbDefaultName = "Default";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取默认数据库
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public SaasMultiTenancyOptions GetDefaultSaasMultiTenancy()
|
public SaasMultiTenancyOptions GetDefaultSaasMultiTenancy()
|
||||||
{
|
{
|
||||||
return new SaasMultiTenancyOptions { Name = TenantDbDefaultName, Url = Url };
|
return new SaasMultiTenancyOptions { Name = TenantDbDefaultName, Url = Url };
|
||||||
}
|
}
|
||||||
public SaasMultiTenancyOptions? GetDefaultMasterSaasMultiTenancy()
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取主数据库
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public SaasMultiTenancyOptions? GetMasterSaasMultiTenancy()
|
||||||
{
|
{
|
||||||
if (EnabledSaasMultiTenancy == false)
|
if (EnabledSaasMultiTenancy == false)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
currentDb.Aop.DataExecuted = this.DataExecuted;
|
currentDb.Aop.DataExecuted = this.DataExecuted;
|
||||||
OnSqlSugarClientConfig(currentDb);
|
OnSqlSugarClientConfig(currentDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ConnectionConfig Build(Action<ConnectionConfig>? action=null)
|
public ConnectionConfig Build(Action<ConnectionConfig>? action=null)
|
||||||
{
|
{
|
||||||
var dbConnOptions = Options;
|
var dbConnOptions = Options;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ISqlSugarClient SqlSugarClient { get; private set; }
|
public ISqlSugarClient SqlSugarClient { get; private set; }
|
||||||
public ICurrentUser CurrentUser => LazyServiceProvider.GetRequiredService<ICurrentUser>();
|
public ICurrentUser CurrentUser => LazyServiceProvider.GetRequiredService<ICurrentUser>();
|
||||||
|
private readonly string MasterTenantDbDefaultName = DbConnOptions.MasterTenantDbDefaultName;
|
||||||
private IAbpLazyServiceProvider LazyServiceProvider { get; }
|
private IAbpLazyServiceProvider LazyServiceProvider { get; }
|
||||||
|
|
||||||
private IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetRequiredService<IGuidGenerator>();
|
private IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetRequiredService<IGuidGenerator>();
|
||||||
@@ -37,7 +37,7 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
|
|
||||||
public IEntityChangeEventHelper EntityChangeEventHelper => LazyServiceProvider.LazyGetService<IEntityChangeEventHelper>(NullEntityChangeEventHelper.Instance);
|
public IEntityChangeEventHelper EntityChangeEventHelper => LazyServiceProvider.LazyGetService<IEntityChangeEventHelper>(NullEntityChangeEventHelper.Instance);
|
||||||
public DbConnOptions Options => LazyServiceProvider.LazyGetRequiredService<IOptions<DbConnOptions>>().Value;
|
public DbConnOptions Options => LazyServiceProvider.LazyGetRequiredService<IOptions<DbConnOptions>>().Value;
|
||||||
|
private ISqlSugarDbConnectionCreator _dbConnectionCreator;
|
||||||
|
|
||||||
public void SetSqlSugarClient(ISqlSugarClient sqlSugarClient)
|
public void SetSqlSugarClient(ISqlSugarClient sqlSugarClient)
|
||||||
{
|
{
|
||||||
@@ -47,16 +47,77 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
{
|
{
|
||||||
LazyServiceProvider = lazyServiceProvider;
|
LazyServiceProvider = lazyServiceProvider;
|
||||||
var connectionCreator = LazyServiceProvider.LazyGetRequiredService<ISqlSugarDbConnectionCreator>();
|
var connectionCreator = LazyServiceProvider.LazyGetRequiredService<ISqlSugarDbConnectionCreator>();
|
||||||
|
_dbConnectionCreator = connectionCreator;
|
||||||
connectionCreator.OnSqlSugarClientConfig = OnSqlSugarClientConfig;
|
connectionCreator.OnSqlSugarClientConfig = OnSqlSugarClientConfig;
|
||||||
connectionCreator.EntityService = EntityService;
|
connectionCreator.EntityService = EntityService;
|
||||||
connectionCreator.DataExecuting = DataExecuting;
|
connectionCreator.DataExecuting = DataExecuting;
|
||||||
connectionCreator.DataExecuted = DataExecuted;
|
connectionCreator.DataExecuted = DataExecuted;
|
||||||
connectionCreator.OnLogExecuting = OnLogExecuting;
|
connectionCreator.OnLogExecuting = OnLogExecuting;
|
||||||
connectionCreator.OnLogExecuted = OnLogExecuted;
|
connectionCreator.OnLogExecuted = OnLogExecuted;
|
||||||
SqlSugarClient = new SqlSugarClient(connectionCreator.Build());
|
SqlSugarClient = new SqlSugarClient(connectionCreator.Build());
|
||||||
connectionCreator.SetDbAop(SqlSugarClient);
|
var connectionStringResolver = LazyServiceProvider.LazyGetRequiredService<IConnectionStringResolver>();
|
||||||
|
var connectionStr = connectionStringResolver.ResolveAsync().Result;
|
||||||
|
var changedDb = DatabaseChange(this, connectionStr);
|
||||||
|
SqlSugarClient = changedDb.SqlSugarClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// db切换多库支持
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dbContext"></param>
|
||||||
|
/// <param name="connectionString"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected virtual SqlSugarDbContext DatabaseChange(SqlSugarDbContext dbContext, string connectionString)
|
||||||
|
{
|
||||||
|
string configId = string.Empty;
|
||||||
|
//没有检测到使用多租户功能,默认使用默认库即可
|
||||||
|
if (string.IsNullOrWhiteSpace(connectionString))
|
||||||
|
{
|
||||||
|
connectionString = dbContext.Options.Url;
|
||||||
|
configId = CurrentTenant.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbOption = dbContext.Options;
|
||||||
|
var db = dbContext.SqlSugarClient.AsTenant();
|
||||||
|
|
||||||
|
//主库的Db切换,当操作的是租户表的时候
|
||||||
|
if (CurrentTenant.Name == MasterTenantDbDefaultName)
|
||||||
|
{
|
||||||
|
//直接切换
|
||||||
|
configId = MasterTenantDbDefaultName;
|
||||||
|
var conStrOrNull = dbOption.GetMasterSaasMultiTenancy();
|
||||||
|
Volo.Abp.Check.NotNull(conStrOrNull, "租户主库未找到");
|
||||||
|
connectionString = conStrOrNull.Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
//租户Db的动态切换
|
||||||
|
//二级缓存
|
||||||
|
var changed = false;
|
||||||
|
if (!db.IsAnyConnection(configId))
|
||||||
|
{
|
||||||
|
var config = _dbConnectionCreator.Build(options =>
|
||||||
|
{
|
||||||
|
options.DbType = dbOption.DbType!.Value;
|
||||||
|
options.ConfigId = configId;//设置库的唯一标识
|
||||||
|
options.IsAutoCloseConnection = true;
|
||||||
|
options.ConnectionString = connectionString;
|
||||||
|
});
|
||||||
|
//添加一个db到当前上下文 (Add部分不线上下文不会共享)
|
||||||
|
db.AddConnection(config);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
var currentDb = db.GetConnection(configId) as ISqlSugarClient;
|
||||||
|
//设置Aop
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
_dbConnectionCreator.SetDbAop(currentDb);
|
||||||
|
}
|
||||||
|
dbContext.SetSqlSugarClient(currentDb);
|
||||||
|
|
||||||
|
return dbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 上下文对象扩展
|
/// 上下文对象扩展
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
|
|
||||||
public async Task CommitAsync(CancellationToken cancellationToken = default)
|
public async Task CommitAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
await _sqlsugarDbContext.SqlSugarClient.Ado.CommitTranAsync();
|
// await _sqlsugarDbContext.SqlSugarClient.Ado.CommitTranAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -29,7 +29,7 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
|
|
||||||
public async Task RollbackAsync(CancellationToken cancellationToken = default)
|
public async Task RollbackAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
await _sqlsugarDbContext.SqlSugarClient.Ado.RollbackTranAsync();
|
// await _sqlsugarDbContext.SqlSugarClient.Ado.RollbackTranAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
public class UnitOfWorkSqlsugarDbContextProvider<TDbContext> : ISugarDbContextProvider<TDbContext> where TDbContext : ISqlSugarDbContext
|
public class UnitOfWorkSqlsugarDbContextProvider<TDbContext> : ISugarDbContextProvider<TDbContext> where TDbContext : ISqlSugarDbContext
|
||||||
{
|
{
|
||||||
private readonly ISqlSugarDbConnectionCreator _dbConnectionCreator;
|
private readonly ISqlSugarDbConnectionCreator _dbConnectionCreator;
|
||||||
private readonly string MasterTenantDbDefaultName = DbConnOptions.MasterTenantDbDefaultName;
|
|
||||||
public ILogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>> Logger { get; set; }
|
public ILogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>> Logger { get; set; }
|
||||||
public IServiceProvider ServiceProvider { get; set; }
|
public IServiceProvider ServiceProvider { get; set; }
|
||||||
|
|
||||||
@@ -59,11 +59,10 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
ContextInstance.Current = (TDbContext)ServiceProvider.GetRequiredService<ISqlSugarDbContext>();
|
ContextInstance.Current = (TDbContext)ServiceProvider.GetRequiredService<ISqlSugarDbContext>();
|
||||||
}
|
}
|
||||||
var dbContext = (TDbContext)ContextInstance.Current;
|
var dbContext = (TDbContext)ContextInstance.Current;
|
||||||
var output = DatabaseChange(dbContext, connectionStringName, connectionString);
|
|
||||||
//提高体验,取消工作单元强制性
|
//提高体验,取消工作单元强制性
|
||||||
//throw new AbpException("A DbContext can only be created inside a unit of work!");
|
//throw new AbpException("A DbContext can only be created inside a unit of work!");
|
||||||
//如果不启用工作单元,创建一个新的db,不开启事务即可
|
//如果不启用工作单元,创建一个新的db,不开启事务即可
|
||||||
return output;
|
return dbContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -100,64 +99,10 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
using (SqlSugarDbContextCreationContext.Use(creationContext))
|
using (SqlSugarDbContextCreationContext.Use(creationContext))
|
||||||
{
|
{
|
||||||
var dbContext = await CreateDbContextAsync(unitOfWork);
|
var dbContext = await CreateDbContextAsync(unitOfWork);
|
||||||
|
return dbContext;
|
||||||
//获取到DB之后,对多租户多库进行处理
|
|
||||||
var changedDbContext = DatabaseChange(dbContext, connectionStringName, connectionString);
|
|
||||||
return changedDbContext;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual TDbContext DatabaseChange(TDbContext dbContext, string configId, string connectionString)
|
|
||||||
{
|
|
||||||
//没有检测到使用多租户功能,默认使用默认库即可
|
|
||||||
if (string.IsNullOrWhiteSpace(connectionString))
|
|
||||||
{
|
|
||||||
connectionString = dbContext.Options.Url;
|
|
||||||
configId = DbConnOptions.TenantDbDefaultName;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dbOption = dbContext.Options;
|
|
||||||
var db = dbContext.SqlSugarClient.AsTenant();
|
|
||||||
//主库的Db切换,当操作的是租户表的时候
|
|
||||||
if (CurrentTenant.Name == MasterTenantDbDefaultName)
|
|
||||||
{
|
|
||||||
//直接切换
|
|
||||||
configId = MasterTenantDbDefaultName;
|
|
||||||
var conStrOrNull = dbOption.GetDefaultMasterSaasMultiTenancy();
|
|
||||||
Volo.Abp.Check.NotNull(conStrOrNull, "租户主库未找到");
|
|
||||||
connectionString = conStrOrNull.Url;
|
|
||||||
}
|
|
||||||
|
|
||||||
//租户Db的动态切换
|
|
||||||
//二级缓存
|
|
||||||
var changed = false;
|
|
||||||
if (!db.IsAnyConnection(configId))
|
|
||||||
{
|
|
||||||
var config = _dbConnectionCreator.Build(options =>
|
|
||||||
{
|
|
||||||
options.DbType = dbOption.DbType!.Value;
|
|
||||||
options.ConfigId = configId;//设置库的唯一标识
|
|
||||||
options.IsAutoCloseConnection = true;
|
|
||||||
options.ConnectionString = connectionString;
|
|
||||||
});
|
|
||||||
//添加一个db到当前上下文 (Add部分不线上下文不会共享)
|
|
||||||
db.AddConnection(config);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
var currentDb = db.GetConnection(configId) as ISqlSugarClient;
|
|
||||||
|
|
||||||
//设置Aop
|
|
||||||
if (changed)
|
|
||||||
{
|
|
||||||
_dbConnectionCreator.SetDbAop(currentDb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
dbContext.SetSqlSugarClient(currentDb);
|
|
||||||
return dbContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected virtual async Task<TDbContext> CreateDbContextAsync(IUnitOfWork unitOfWork)
|
protected virtual async Task<TDbContext> CreateDbContextAsync(IUnitOfWork unitOfWork)
|
||||||
{
|
{
|
||||||
return unitOfWork.Options.IsTransactional
|
return unitOfWork.Options.IsTransactional
|
||||||
@@ -182,7 +127,7 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
);
|
);
|
||||||
unitOfWork.AddTransactionApi(transactionApiKey, transaction);
|
unitOfWork.AddTransactionApi(transactionApiKey, transaction);
|
||||||
|
|
||||||
await dbContext.SqlSugarClient.Ado.BeginTranAsync();
|
// await dbContext.SqlSugarClient.Ado.BeginTranAsync();
|
||||||
return dbContext;
|
return dbContext;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -110,17 +110,18 @@ namespace Yi.Framework.TenantManagement.Application
|
|||||||
[HttpPut("tenant/init/{id}")]
|
[HttpPut("tenant/init/{id}")]
|
||||||
public async Task InitAsync([FromRoute]Guid id)
|
public async Task InitAsync([FromRoute]Guid id)
|
||||||
{
|
{
|
||||||
using (CurrentTenant.Change(id))
|
using (CurrentTenant.Change(id,"test"))
|
||||||
{
|
{
|
||||||
CodeFirst(await _repository.GetDbContextAsync());
|
await CodeFirst(this.LazyServiceProvider);
|
||||||
await _dataSeeder.SeedAsync(id);
|
await _dataSeeder.SeedAsync(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CodeFirst(ISqlSugarClient db)
|
private async Task CodeFirst(IServiceProvider service)
|
||||||
{
|
{
|
||||||
|
var moduleContainer = service.GetRequiredService<IModuleContainer>();
|
||||||
var moduleContainer = ServiceProvider.GetRequiredService<IModuleContainer>();
|
var db = await _repository.GetDbContextAsync();
|
||||||
|
|
||||||
//尝试创建数据库
|
//尝试创建数据库
|
||||||
db.DbMaintenance.CreateDatabase();
|
db.DbMaintenance.CreateDatabase();
|
||||||
@@ -131,12 +132,11 @@ namespace Yi.Framework.TenantManagement.Application
|
|||||||
types.AddRange(module.Assembly.GetTypes()
|
types.AddRange(module.Assembly.GetTypes()
|
||||||
.Where(x => x.GetCustomAttribute<IgnoreCodeFirstAttribute>() == null)
|
.Where(x => x.GetCustomAttribute<IgnoreCodeFirstAttribute>() == null)
|
||||||
.Where(x => x.GetCustomAttribute<SugarTable>() != null)
|
.Where(x => x.GetCustomAttribute<SugarTable>() != null)
|
||||||
.Where(x=>x.GetCustomAttribute<MasterTenantAttribute>()==null)
|
|
||||||
.Where(x => x.GetCustomAttribute<SplitTableAttribute>() is null));
|
.Where(x => x.GetCustomAttribute<SplitTableAttribute>() is null));
|
||||||
}
|
}
|
||||||
if (types.Count > 0)
|
if (types.Count > 0)
|
||||||
{
|
{
|
||||||
db.CodeFirst.InitTables(types.ToArray());
|
db.CopyNew().CodeFirst.InitTables(types.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
168
Yi.Abp.Net8/src/Yi.Abp.Web/DefaultConnectionStringResolver2.cs
Normal file
168
Yi.Abp.Net8/src/Yi.Abp.Web/DefaultConnectionStringResolver2.cs
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Volo.Abp.Data;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Volo.Abp.MultiTenancy;
|
||||||
|
|
||||||
|
[Dependency(ReplaceServices = true)]
|
||||||
|
public class MultiTenantConnectionStringResolver2 : DefaultConnectionStringResolver
|
||||||
|
{
|
||||||
|
private readonly ICurrentTenant _currentTenant;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
public MultiTenantConnectionStringResolver2(
|
||||||
|
IOptionsMonitor<AbpDbConnectionOptions> options,
|
||||||
|
ICurrentTenant currentTenant,
|
||||||
|
IServiceProvider serviceProvider)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
_currentTenant = currentTenant;
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<string> ResolveAsync(string? connectionStringName = null)
|
||||||
|
{
|
||||||
|
if (_currentTenant.Id == null)
|
||||||
|
{
|
||||||
|
//No current tenant, fallback to default logic
|
||||||
|
return await base.ResolveAsync(connectionStringName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tenant = await FindTenantConfigurationAsync(_currentTenant.Id.Value);
|
||||||
|
|
||||||
|
if (tenant == null || tenant.ConnectionStrings.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
//Tenant has not defined any connection string, fallback to default logic
|
||||||
|
return await base.ResolveAsync(connectionStringName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tenantDefaultConnectionString = tenant.ConnectionStrings?.Default;
|
||||||
|
|
||||||
|
//Requesting default connection string...
|
||||||
|
//if (connectionStringName == null ||
|
||||||
|
// connectionStringName == ConnectionStrings.DefaultConnectionStringName)
|
||||||
|
//{
|
||||||
|
// //Return tenant's default or global default
|
||||||
|
// return !tenantDefaultConnectionString.IsNullOrWhiteSpace()
|
||||||
|
// ? tenantDefaultConnectionString!
|
||||||
|
// : Options.ConnectionStrings.Default!;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//Requesting specific connection string...
|
||||||
|
var connString = tenant.ConnectionStrings?.FirstOrDefault().Value;
|
||||||
|
if (!connString.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
//Found for the tenant
|
||||||
|
return connString!;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fallback to the mapped database for the specific connection string
|
||||||
|
var database = Options.Databases.GetMappedDatabaseOrNull(connectionStringName);
|
||||||
|
if (database != null && database.IsUsedByTenants)
|
||||||
|
{
|
||||||
|
connString = tenant.ConnectionStrings?.GetOrDefault(database.DatabaseName);
|
||||||
|
if (!connString.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
//Found for the tenant
|
||||||
|
return connString!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fallback to tenant's default connection string if available
|
||||||
|
if (!tenantDefaultConnectionString.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return tenantDefaultConnectionString!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await base.ResolveAsync(connectionStringName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use ResolveAsync method.")]
|
||||||
|
public override string Resolve(string? connectionStringName = null)
|
||||||
|
{
|
||||||
|
if (_currentTenant.Id == null)
|
||||||
|
{
|
||||||
|
//No current tenant, fallback to default logic
|
||||||
|
return base.Resolve(connectionStringName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tenant = FindTenantConfiguration(_currentTenant.Id.Value);
|
||||||
|
|
||||||
|
if (tenant == null || tenant.ConnectionStrings.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
//Tenant has not defined any connection string, fallback to default logic
|
||||||
|
return base.Resolve(connectionStringName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tenantDefaultConnectionString = tenant.ConnectionStrings?.Default;
|
||||||
|
|
||||||
|
//Requesting default connection string...
|
||||||
|
if (connectionStringName == null ||
|
||||||
|
connectionStringName == ConnectionStrings.DefaultConnectionStringName)
|
||||||
|
{
|
||||||
|
//Return tenant's default or global default
|
||||||
|
return !tenantDefaultConnectionString.IsNullOrWhiteSpace()
|
||||||
|
? tenantDefaultConnectionString!
|
||||||
|
: Options.ConnectionStrings.Default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Requesting specific connection string...
|
||||||
|
var connString = tenant.ConnectionStrings?.GetOrDefault(connectionStringName);
|
||||||
|
if (!connString.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
//Found for the tenant
|
||||||
|
return connString!;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fallback to tenant's default connection string if available
|
||||||
|
if (!tenantDefaultConnectionString.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return tenantDefaultConnectionString!;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Try to find the specific connection string for given name
|
||||||
|
var connStringInOptions = Options.ConnectionStrings.GetOrDefault(connectionStringName);
|
||||||
|
if (!connStringInOptions.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return connStringInOptions!;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fallback to the global default connection string
|
||||||
|
var defaultConnectionString = Options.ConnectionStrings.Default;
|
||||||
|
if (!defaultConnectionString.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return defaultConnectionString!;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AbpException("No connection string defined!");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual async Task<TenantConfiguration?> FindTenantConfigurationAsync(Guid tenantId)
|
||||||
|
{
|
||||||
|
using (var serviceScope = _serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var tenantStore = serviceScope
|
||||||
|
.ServiceProvider
|
||||||
|
.GetRequiredService<ITenantStore>();
|
||||||
|
|
||||||
|
return await tenantStore.FindAsync(tenantId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use FindTenantConfigurationAsync method.")]
|
||||||
|
protected virtual TenantConfiguration? FindTenantConfiguration(Guid tenantId)
|
||||||
|
{
|
||||||
|
using (var serviceScope = _serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var tenantStore = serviceScope
|
||||||
|
.ServiceProvider
|
||||||
|
.GetRequiredService<ITenantStore>();
|
||||||
|
|
||||||
|
return tenantStore.Find(tenantId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
using Volo.Abp.Data;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
using Yi.Abp.Web;
|
using Yi.Abp.Web;
|
||||||
|
|
||||||
//创建日志,可使用{SourceContext}记录
|
//创建日志,可使用{SourceContext}记录
|
||||||
@@ -23,6 +26,7 @@ try
|
|||||||
builder.Host.UseAutofac();
|
builder.Host.UseAutofac();
|
||||||
builder.Host.UseSerilog();
|
builder.Host.UseSerilog();
|
||||||
await builder.Services.AddApplicationAsync<YiAbpWebModule>();
|
await builder.Services.AddApplicationAsync<YiAbpWebModule>();
|
||||||
|
builder.Services.Replace(new ServiceDescriptor(typeof(IConnectionStringResolver), typeof(MultiTenantConnectionStringResolver2),ServiceLifetime.Transient));
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
await app.InitializeApplicationAsync();
|
await app.InitializeApplicationAsync();
|
||||||
await app.RunAsync();
|
await app.RunAsync();
|
||||||
|
|||||||
Binary file not shown.
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/yi-test.db
Normal file
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/yi-test.db
Normal file
Binary file not shown.
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/yi-test2.db
Normal file
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/yi-test2.db
Normal file
Binary file not shown.
Reference in New Issue
Block a user