using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace NPin.Framework.TenantManagement.Domain;
///
/// 数据库连接字符串解析器,替代原有
///
[Dependency(ReplaceServices = true)]
public class NPinMultiTenantConnectionStringResolver : DefaultConnectionStringResolver
{
private readonly ICurrentTenant _currentTenant;
private readonly IServiceProvider _serviceProvider;
public NPinMultiTenantConnectionStringResolver(IOptionsMonitor options,
ICurrentTenant currentTenant, IServiceProvider serviceProvider) : base(options)
{
_currentTenant = currentTenant;
_serviceProvider = serviceProvider;
}
public override async Task ResolveAsync(string? connectionStringName = null)
{
if (_currentTenant.Id == null)
{
// 无租户信息,使用原有解析器
return await base.ResolveAsync(connectionStringName);
}
// 通过Store寻找租户缓存
var tenant = await FindTenantConfigurationAsync(_currentTenant.Id.Value);
if (tenant == null || tenant.ConnectionStrings.IsNullOrEmpty())
{
// 找不到租户缓存,使用原有解析器
return await base.ResolveAsync(connectionStringName);
}
var tenantDefaultConnectionString = tenant.ConnectionStrings?.Default;
var connString = tenant.ConnectionStrings?.FirstOrDefault().Value;
if (!connString.IsNullOrWhiteSpace())
{
return connString;
}
// 库隔离
var database = Options.Databases.GetMappedDatabaseOrNull(connectionStringName);
if (database is { IsUsedByTenants: true })
{
connString = tenant.ConnectionStrings?.GetOrDefault(database.DatabaseName);
if (!connString.IsNullOrWhiteSpace())
{
return connString;
}
}
if (!tenantDefaultConnectionString.IsNullOrWhiteSpace())
{
return tenantDefaultConnectionString;
}
return await base.ResolveAsync(connectionStringName);
}
protected virtual async Task FindTenantConfigurationAsync(Guid tenantId)
{
using var serviceScope = _serviceProvider.CreateScope();
var tenantStore = serviceScope
.ServiceProvider
.GetRequiredService();
return await tenantStore.FindAsync(tenantId);
}
[Obsolete("Use ResolveAsync Instead.")]
public override string Resolve(string? connectionStringName = null)
{
if (_currentTenant.Id == null)
{
// 无租户信息,使用原有解析器
return base.Resolve(connectionStringName);
}
// 通过Store寻找租户缓存
var tenant = FindTenantConfiguration(_currentTenant.Id.Value);
if (tenant == null || tenant.ConnectionStrings.IsNullOrEmpty())
{
// 找不到租户缓存,使用原有解析器
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!");
}
[Obsolete("Use FindTenantConfigurationAsync Instead.")]
protected virtual TenantConfiguration? FindTenantConfiguration(Guid tenantId)
{
using var serviceScope = _serviceProvider.CreateScope();
var tenantStore = serviceScope
.ServiceProvider
.GetRequiredService();
return tenantStore.Find(tenantId);
}
}