feat: 优化多租户配置
This commit is contained in:
@@ -22,8 +22,10 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
|
|
||||||
private IAbpLazyServiceProvider LazyServiceProvider { get; }
|
private IAbpLazyServiceProvider LazyServiceProvider { get; }
|
||||||
|
|
||||||
|
private TenantConfigurationWrapper TenantConfigurationWrapper=> LazyServiceProvider.LazyGetRequiredService<TenantConfigurationWrapper>();
|
||||||
private ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService<ICurrentTenant>();
|
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>();
|
private ISerializeService SerializeService => LazyServiceProvider.LazyGetRequiredService<ISerializeService>();
|
||||||
|
|
||||||
@@ -36,19 +38,13 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
{
|
{
|
||||||
LazyServiceProvider = lazyServiceProvider;
|
LazyServiceProvider = lazyServiceProvider;
|
||||||
|
|
||||||
var connectionString = GetCurrentConnectionString();
|
var tenantConfiguration= AsyncHelper.RunSync(async () =>await TenantConfigurationWrapper.GetAsync());
|
||||||
|
|
||||||
var connectionConfig =BuildConnectionConfig(action: options =>
|
var connectionConfig =BuildConnectionConfig(action: options =>
|
||||||
{
|
{
|
||||||
options.ConnectionString = connectionString;
|
options.ConnectionString =tenantConfiguration.GetCurrentConnectionString();
|
||||||
options.DbType = GetCurrentDbType();
|
options.DbType = GetCurrentDbType(tenantConfiguration.GetCurrentConnectionName());
|
||||||
});
|
});
|
||||||
// var connectionConfig = ConnectionConfigCache.GetOrAdd(connectionString, (_) =>
|
|
||||||
// BuildConnectionConfig(action: options =>
|
|
||||||
// {
|
|
||||||
// options.ConnectionString = connectionString;
|
|
||||||
// options.DbType = GetCurrentDbType();
|
|
||||||
// }));
|
|
||||||
SqlSugarClient = new SqlSugarClient(connectionConfig);
|
SqlSugarClient = new SqlSugarClient(connectionConfig);
|
||||||
//生命周期,以下都可以直接使用sqlsugardb了
|
//生命周期,以下都可以直接使用sqlsugardb了
|
||||||
|
|
||||||
@@ -189,38 +185,15 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
return connectionConfig;
|
return connectionConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
protected virtual DbType GetCurrentDbType(string tenantName)
|
||||||
/// db切换多库支持
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected virtual string GetCurrentConnectionString()
|
|
||||||
{
|
{
|
||||||
var connectionStringResolver = LazyServiceProvider.LazyGetRequiredService<IConnectionStringResolver>();
|
if (tenantName == ConnectionStrings.DefaultConnectionStringName)
|
||||||
var connectionString =
|
|
||||||
AsyncHelper.RunSync(() => connectionStringResolver.ResolveAsync());
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(connectionString))
|
|
||||||
{
|
{
|
||||||
Check.NotNull(Options.Url, "dbUrl未配置");
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return Options.DbType!.Value;
|
||||||
}
|
}
|
||||||
|
var dbTypeFromTenantName = GetDbTypeFromTenantName(tenantName);
|
||||||
|
return dbTypeFromTenantName!.Value;
|
||||||
|
}
|
||||||
|
|
||||||
//根据租户name进行匹配db类型: Test_Sqlite,[来自AI]
|
//根据租户name进行匹配db类型: Test_Sqlite,[来自AI]
|
||||||
private DbType? GetDbTypeFromTenantName(string name)
|
private DbType? GetDbTypeFromTenantName(string name)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -15,8 +15,8 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
{
|
{
|
||||||
public ILogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>> Logger { get; set; }
|
public ILogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>> Logger { get; set; }
|
||||||
public IServiceProvider ServiceProvider { get; set; }
|
public IServiceProvider ServiceProvider { get; set; }
|
||||||
|
|
||||||
private static AsyncLocalDbContextAccessor ContextInstance => AsyncLocalDbContextAccessor.Instance;
|
private static AsyncLocalDbContextAccessor ContextInstance => AsyncLocalDbContextAccessor.Instance;
|
||||||
|
protected readonly TenantConfigurationWrapper _tenantConfigurationWrapper;
|
||||||
protected readonly IUnitOfWorkManager UnitOfWorkManager;
|
protected readonly IUnitOfWorkManager UnitOfWorkManager;
|
||||||
protected readonly IConnectionStringResolver ConnectionStringResolver;
|
protected readonly IConnectionStringResolver ConnectionStringResolver;
|
||||||
protected readonly ICancellationTokenProvider CancellationTokenProvider;
|
protected readonly ICancellationTokenProvider CancellationTokenProvider;
|
||||||
@@ -26,26 +26,25 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
IUnitOfWorkManager unitOfWorkManager,
|
IUnitOfWorkManager unitOfWorkManager,
|
||||||
IConnectionStringResolver connectionStringResolver,
|
IConnectionStringResolver connectionStringResolver,
|
||||||
ICancellationTokenProvider cancellationTokenProvider,
|
ICancellationTokenProvider cancellationTokenProvider,
|
||||||
ICurrentTenant currentTenant
|
ICurrentTenant currentTenant, TenantConfigurationWrapper tenantConfigurationWrapper)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
UnitOfWorkManager = unitOfWorkManager;
|
UnitOfWorkManager = unitOfWorkManager;
|
||||||
ConnectionStringResolver = connectionStringResolver;
|
ConnectionStringResolver = connectionStringResolver;
|
||||||
CancellationTokenProvider = cancellationTokenProvider;
|
CancellationTokenProvider = cancellationTokenProvider;
|
||||||
CurrentTenant = currentTenant;
|
CurrentTenant = currentTenant;
|
||||||
|
_tenantConfigurationWrapper = tenantConfigurationWrapper;
|
||||||
Logger = NullLogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>>.Instance;
|
Logger = NullLogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>>.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<TDbContext> GetDbContextAsync()
|
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 dbContextKey = $"{this.GetType().Name}_{connectionString}";
|
||||||
|
|
||||||
|
|
||||||
var unitOfWork = UnitOfWorkManager.Current;
|
var unitOfWork = UnitOfWorkManager.Current;
|
||||||
if (unitOfWork == null )
|
if (unitOfWork == null )
|
||||||
{
|
{
|
||||||
@@ -67,8 +66,6 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
databaseApi = new SqlSugarDatabaseApi(
|
databaseApi = new SqlSugarDatabaseApi(
|
||||||
await CreateDbContextAsync(unitOfWork, connectionStringName, connectionString)
|
await CreateDbContextAsync(unitOfWork, connectionStringName, connectionString)
|
||||||
);
|
);
|
||||||
|
|
||||||
//await Console.Out.WriteLineAsync(">>>----------------实例化了db"+ ((SqlSugarDatabaseApi)databaseApi).DbContext.SqlSugarClient.ContextID.ToString());
|
|
||||||
//创建的db加入到当前工作单元中
|
//创建的db加入到当前工作单元中
|
||||||
unitOfWork.AddDatabaseApi(dbContextKey, databaseApi);
|
unitOfWork.AddDatabaseApi(dbContextKey, databaseApi);
|
||||||
|
|
||||||
@@ -98,7 +95,7 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
|||||||
protected virtual async Task<TDbContext> CreateDbContextWithTransactionAsync(IUnitOfWork unitOfWork)
|
protected virtual async Task<TDbContext> CreateDbContextWithTransactionAsync(IUnitOfWork unitOfWork)
|
||||||
{
|
{
|
||||||
//事务key
|
//事务key
|
||||||
var transactionApiKey = $"SqlsugarCore_{SqlSugarDbContextCreationContext.Current.ConnectionString}";
|
var transactionApiKey = $"SqlSugarCore_{SqlSugarDbContextCreationContext.Current.ConnectionString}";
|
||||||
|
|
||||||
//尝试查找事务
|
//尝试查找事务
|
||||||
var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as SqlSugarTransactionApi;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ using Volo.Abp.Data;
|
|||||||
using Volo.Abp.Domain;
|
using Volo.Abp.Domain;
|
||||||
using Volo.Abp.Domain.Repositories;
|
using Volo.Abp.Domain.Repositories;
|
||||||
using Volo.Abp.Guids;
|
using Volo.Abp.Guids;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
|
using Volo.Abp.MultiTenancy.ConfigurationStore;
|
||||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
using Yi.Framework.SqlSugarCore.Repositories;
|
using Yi.Framework.SqlSugarCore.Repositories;
|
||||||
using Yi.Framework.SqlSugarCore.Uow;
|
using Yi.Framework.SqlSugarCore.Uow;
|
||||||
@@ -69,7 +71,15 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
var dbConfig = section.Get<DbConnOptions>();
|
var dbConfig = section.Get<DbConnOptions>();
|
||||||
//将默认db传递给abp连接字符串模块
|
//将默认db传递给abp连接字符串模块
|
||||||
Configure<AbpDbConnectionOptions>(x => { x.ConnectionStrings.Default = dbConfig.Url; });
|
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>();
|
context.Services.AddYiDbContext<DefaultSqlSugarDbContext>();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,8 @@ public class YiMultiTenantConnectionStringResolver : DefaultConnectionStringReso
|
|||||||
: Options.ConnectionStrings.Default!;
|
: Options.ConnectionStrings.Default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Requesting specific connection string...
|
//Requesting specific connection string...
|
||||||
var connString = tenant.ConnectionStrings?.FirstOrDefault().Value;
|
var connString = tenant.ConnectionStrings?.GetOrDefault(connectionStringName);
|
||||||
if (!connString.IsNullOrWhiteSpace())
|
if (!connString.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
//Found for the tenant
|
//Found for the tenant
|
||||||
|
|||||||
Reference in New Issue
Block a user