feat: 优化多租户配置

This commit is contained in:
chenchun
2025-02-21 18:00:06 +08:00
parent 1fd4f2754a
commit 753b5b0a26
5 changed files with 113 additions and 71 deletions

View File

@@ -22,8 +22,10 @@ namespace Yi.Framework.SqlSugarCore
private IAbpLazyServiceProvider LazyServiceProvider { get; }
private TenantConfigurationWrapper TenantConfigurationWrapper=> LazyServiceProvider.LazyGetRequiredService<TenantConfigurationWrapper>();
private ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService<ICurrentTenant>();
public DbConnOptions Options => LazyServiceProvider.LazyGetRequiredService<IOptions<DbConnOptions>>().Value;
private DbConnOptions Options => LazyServiceProvider.LazyGetRequiredService<IOptions<DbConnOptions>>().Value;
private ISerializeService SerializeService => LazyServiceProvider.LazyGetRequiredService<ISerializeService>();
@@ -36,19 +38,13 @@ namespace Yi.Framework.SqlSugarCore
{
LazyServiceProvider = lazyServiceProvider;
var connectionString = GetCurrentConnectionString();
var tenantConfiguration= AsyncHelper.RunSync(async () =>await TenantConfigurationWrapper.GetAsync());
var connectionConfig =BuildConnectionConfig(action: options =>
{
options.ConnectionString = connectionString;
options.DbType = GetCurrentDbType();
options.ConnectionString =tenantConfiguration.GetCurrentConnectionString();
options.DbType = GetCurrentDbType(tenantConfiguration.GetCurrentConnectionName());
});
// var connectionConfig = ConnectionConfigCache.GetOrAdd(connectionString, (_) =>
// BuildConnectionConfig(action: options =>
// {
// options.ConnectionString = connectionString;
// options.DbType = GetCurrentDbType();
// }));
SqlSugarClient = new SqlSugarClient(connectionConfig);
//生命周期以下都可以直接使用sqlsugardb了
@@ -189,37 +185,14 @@ namespace Yi.Framework.SqlSugarCore
return connectionConfig;
}
/// <summary>
/// db切换多库支持
/// </summary>
/// <returns></returns>
protected virtual string GetCurrentConnectionString()
protected virtual DbType GetCurrentDbType(string tenantName)
{
var connectionStringResolver = LazyServiceProvider.LazyGetRequiredService<IConnectionStringResolver>();
var connectionString =
AsyncHelper.RunSync(() => connectionStringResolver.ResolveAsync());
if (string.IsNullOrWhiteSpace(connectionString))
if (tenantName == ConnectionStrings.DefaultConnectionStringName)
{
Check.NotNull(Options.Url, "dbUrl未配置");
return Options.DbType!.Value;
}
return connectionString!;
}
protected virtual DbType GetCurrentDbType()
{
if (CurrentTenant.Name is not null)
{
var dbTypeFromTenantName = GetDbTypeFromTenantName(CurrentTenant.Name);
if (dbTypeFromTenantName is not null)
{
return dbTypeFromTenantName.Value;
}
}
Check.NotNull(Options.DbType, "默认DbType未配置");
return Options.DbType!.Value;
var dbTypeFromTenantName = GetDbTypeFromTenantName(tenantName);
return dbTypeFromTenantName!.Value;
}
//根据租户name进行匹配db类型: Test_Sqlite[来自AI]

View File

@@ -0,0 +1,79 @@
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace Yi.Framework.SqlSugarCore;
/// <summary>
/// 租户配置
/// </summary>
public class TenantConfigurationWrapper : ITransientDependency
{
private ICurrentTenant _currentTenant;
private ITenantStore _tenantStore;
public TenantConfigurationWrapper(ICurrentTenant currentTenant, ITenantStore tenantStore)
{
_currentTenant = currentTenant;
_tenantStore = tenantStore;
}
/// <summary>
/// 获取租户信息
/// </summary>
/// <returns></returns>
public async Task<TenantConfiguration?> GetAsync()
{
if (_currentTenant.Id is not null)
{
return await _tenantStore.FindAsync(_currentTenant.Id.Value);
}
else if (!string.IsNullOrEmpty(_currentTenant.Name))
{
return await _tenantStore.FindAsync(_currentTenant.Name);
}
else
{
return await _tenantStore.FindAsync(ConnectionStrings.DefaultConnectionStringName);
}
}
/// <summary>
/// 获取当前连接字符串
/// </summary>
/// <returns></returns>
public async Task<string> GetCurrentConnectionStringAsync()
{
return (await GetAsync()).ConnectionStrings.Default!;
}
/// <summary>
/// 获取当前连接名
/// </summary>
/// <returns></returns>
public async Task<string> GetCurrentConnectionNameAsync()
{
return (await GetAsync()).Name;
}
}
public static class TenantConfigurationExtensions
{
/// <summary>
/// 获取当前连接字符串
/// </summary>
/// <returns></returns>
public static string GetCurrentConnectionString(this TenantConfiguration tenantConfiguration)
{
return tenantConfiguration.ConnectionStrings.Default!;
}
/// <summary>
/// 获取当前连接名
/// </summary>
/// <returns></returns>
public static string GetCurrentConnectionName(this TenantConfiguration tenantConfiguration)
{
return tenantConfiguration.Name;
}
}

View File

@@ -15,8 +15,8 @@ namespace Yi.Framework.SqlSugarCore.Uow
{
public ILogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>> Logger { get; set; }
public IServiceProvider ServiceProvider { get; set; }
private static AsyncLocalDbContextAccessor ContextInstance => AsyncLocalDbContextAccessor.Instance;
protected readonly TenantConfigurationWrapper _tenantConfigurationWrapper;
protected readonly IUnitOfWorkManager UnitOfWorkManager;
protected readonly IConnectionStringResolver ConnectionStringResolver;
protected readonly ICancellationTokenProvider CancellationTokenProvider;
@@ -26,26 +26,25 @@ namespace Yi.Framework.SqlSugarCore.Uow
IUnitOfWorkManager unitOfWorkManager,
IConnectionStringResolver connectionStringResolver,
ICancellationTokenProvider cancellationTokenProvider,
ICurrentTenant currentTenant
)
ICurrentTenant currentTenant, TenantConfigurationWrapper tenantConfigurationWrapper)
{
UnitOfWorkManager = unitOfWorkManager;
ConnectionStringResolver = connectionStringResolver;
CancellationTokenProvider = cancellationTokenProvider;
CurrentTenant = currentTenant;
_tenantConfigurationWrapper = tenantConfigurationWrapper;
Logger = NullLogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>>.Instance;
}
public virtual async Task<TDbContext> GetDbContextAsync()
{
var connectionStringName = ConnectionStrings.DefaultConnectionStringName;
//获取当前连接字符串,未多租户时,默认为空
var connectionString = await ResolveConnectionStringAsync(connectionStringName);
var tenantConfiguration= await _tenantConfigurationWrapper.GetAsync();
//由于sqlsugar的特殊性没有db区分不再使用连接字符串解析器
var connectionStringName = tenantConfiguration.GetCurrentConnectionName();
var connectionString = tenantConfiguration.GetCurrentConnectionString();
var dbContextKey = $"{this.GetType().Name}_{connectionString}";
var unitOfWork = UnitOfWorkManager.Current;
if (unitOfWork == null )
{
@@ -67,8 +66,6 @@ namespace Yi.Framework.SqlSugarCore.Uow
databaseApi = new SqlSugarDatabaseApi(
await CreateDbContextAsync(unitOfWork, connectionStringName, connectionString)
);
//await Console.Out.WriteLineAsync(">>>----------------实例化了db"+ ((SqlSugarDatabaseApi)databaseApi).DbContext.SqlSugarClient.ContextID.ToString());
//创建的db加入到当前工作单元中
unitOfWork.AddDatabaseApi(dbContextKey, databaseApi);
@@ -98,7 +95,7 @@ namespace Yi.Framework.SqlSugarCore.Uow
protected virtual async Task<TDbContext> CreateDbContextWithTransactionAsync(IUnitOfWork unitOfWork)
{
//事务key
var transactionApiKey = $"SqlsugarCore_{SqlSugarDbContextCreationContext.Current.ConnectionString}";
var transactionApiKey = $"SqlSugarCore_{SqlSugarDbContextCreationContext.Current.ConnectionString}";
//尝试查找事务
var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as SqlSugarTransactionApi;
@@ -123,20 +120,5 @@ namespace Yi.Framework.SqlSugarCore.Uow
}
protected virtual async Task<string> ResolveConnectionStringAsync(string connectionStringName)
{
if (typeof(TDbContext).IsDefined(typeof(IgnoreMultiTenancyAttribute), false))
{
using (CurrentTenant.Change(null))
{
return await ConnectionStringResolver.ResolveAsync(connectionStringName);
}
}
return await ConnectionStringResolver.ResolveAsync(connectionStringName);
}
}
}

View File

@@ -10,6 +10,8 @@ using Volo.Abp.Data;
using Volo.Abp.Domain;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.MultiTenancy.ConfigurationStore;
using Yi.Framework.SqlSugarCore.Abstractions;
using Yi.Framework.SqlSugarCore.Repositories;
using Yi.Framework.SqlSugarCore.Uow;
@@ -69,7 +71,15 @@ namespace Yi.Framework.SqlSugarCore
var dbConfig = section.Get<DbConnOptions>();
//将默认db传递给abp连接字符串模块
Configure<AbpDbConnectionOptions>(x => { x.ConnectionStrings.Default = dbConfig.Url; });
//配置abp默认租户
Configure<AbpDefaultTenantStoreOptions>(x => { x.Tenants.AddFirst(new TenantConfiguration
{
Id = Guid.Empty,
Name =$"{ConnectionStrings.DefaultConnectionStringName}",
NormalizedName = ConnectionStrings.DefaultConnectionStringName,
ConnectionStrings = new ConnectionStrings(){{ConnectionStrings.DefaultConnectionStringName,dbConfig.Url}},
IsActive = true
});});
context.Services.AddYiDbContext<DefaultSqlSugarDbContext>();
return Task.CompletedTask;
}

View File

@@ -53,10 +53,8 @@ public class YiMultiTenantConnectionStringResolver : DefaultConnectionStringReso
: Options.ConnectionStrings.Default!;
}
//Requesting specific connection string...
var connString = tenant.ConnectionStrings?.FirstOrDefault().Value;
var connString = tenant.ConnectionStrings?.GetOrDefault(connectionStringName);
if (!connString.IsNullOrWhiteSpace())
{
//Found for the tenant