using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; 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; // 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!; } // 库隔离 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); } }