using Abp.Configuration.Startup; using Abp.Domain.Uow; using Abp.Extensions; using Abp.MultiTenancy; using Abp.Runtime.Session; using IwbZero.MultiTenancy; namespace IwbZero.EntityFramework { /// /// Implements to dynamically resolve /// connection string for a multi tenant application. /// public class DbPerTenantConnectionStringResolver : DefaultConnectionStringResolver, IDbPerTenantConnectionStringResolver { /// /// Reference to the session. /// public IAbpSession 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 = NullAbpSession.Instance; } public override string GetNameOrConnectionString(ConnectionStringResolveArgs args) { if (args.MultiTenancySide == 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==null||tenantCacheItem.ConnectionString.IsNullOrEmpty()) { //Tenant has not dedicated database return base.GetNameOrConnectionString(args); } return tenantCacheItem.ConnectionString; } protected virtual int? GetCurrentTenantId() { return _currentUnitOfWorkProvider.Current != null ? _currentUnitOfWorkProvider.Current.GetTenantId() : AbpSession.TenantId; } } }