using Abp.Configuration.Startup;
using Abp.Domain.Uow;
using Abp.Extensions;
using Abp.Runtime.Session;
using VberZero.MultiTenancy;
using VberZero.Session;
namespace VberZero.EntityFramework;
///
/// Implements to dynamically resolve
/// connection string for a multi tenant application.
///
public class DbPerTenantConnectionStringResolver : DefaultConnectionStringResolver, IDbPerTenantConnectionStringResolver
{
///
/// Reference to the session.
///
public IVzSession AbpSession { get; set; }
private readonly ICurrentUnitOfWorkProvider _currentUnitOfWorkProvider;
private readonly ITenantCache _tenantCache;
///
/// Initializes a new instance of the class.
///
public DbPerTenantConnectionStringResolver(
IAbpStartupConfiguration configuration,
ICurrentUnitOfWorkProvider currentUnitOfWorkProvider,
ITenantCache tenantCache)
: base(configuration)
{
_currentUnitOfWorkProvider = currentUnitOfWorkProvider;
_tenantCache = tenantCache;
AbpSession = NullVzSession.Instance;
}
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
if (args.MultiTenancySide == Abp.MultiTenancy.MultiTenancySides.Host)
{
return GetNameOrConnectionString(new DbPerTenantConnectionStringResolveArgs(null, args));
}
return GetNameOrConnectionString(new DbPerTenantConnectionStringResolveArgs(GetCurrentTenantId(), args));
}
public virtual string GetNameOrConnectionString(DbPerTenantConnectionStringResolveArgs args)
{
if (args.TenantId == null)
{
//Requested for host
return base.GetNameOrConnectionString(args);
}
var tenantCacheItem = _tenantCache.Get(args.TenantId.Value);
if (tenantCacheItem.ConnectionString.IsNullOrEmpty())
{
//Tenant has not dedicated database
return base.GetNameOrConnectionString(args);
}
return tenantCacheItem.ConnectionString;
}
public override async Task GetNameOrConnectionStringAsync(ConnectionStringResolveArgs args)
{
if (args.MultiTenancySide == Abp.MultiTenancy.MultiTenancySides.Host)
{
return await GetNameOrConnectionStringAsync(new DbPerTenantConnectionStringResolveArgs(null, args));
}
return await GetNameOrConnectionStringAsync(new DbPerTenantConnectionStringResolveArgs(GetCurrentTenantId(), args));
}
public virtual async Task GetNameOrConnectionStringAsync(DbPerTenantConnectionStringResolveArgs args)
{
if (args.TenantId == null)
{
//Requested for host
return await base.GetNameOrConnectionStringAsync(args);
}
var tenantCacheItem = await _tenantCache.GetAsync(args.TenantId.Value);
if (tenantCacheItem.ConnectionString.IsNullOrEmpty())
{
//Tenant has not dedicated database
return await base.GetNameOrConnectionStringAsync(args);
}
return tenantCacheItem.ConnectionString;
}
protected virtual int? GetCurrentTenantId()
{
return _currentUnitOfWorkProvider.Current != null
? _currentUnitOfWorkProvider.Current.GetTenantId()
: AbpSession.TenantId;
}
}