mirror of https://github.com/abpframework/abp.git
7 changed files with 168 additions and 3 deletions
@ -0,0 +1,10 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.Data.MultiTenancy |
||||
|
{ |
||||
|
public interface ITenantConnectionStringStore |
||||
|
{ |
||||
|
[CanBeNull] |
||||
|
string GetConnectionStringOrNull([NotNull] string tenantId, [CanBeNull] string databaseName); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Data.MultiTenancy |
||||
|
{ |
||||
|
//TODO: It would be better to use composition over inheritance on connection string resolve progress!
|
||||
|
//TODO: Create a replace service registration convention, instead of custom registration in AbpMultiTenancyModule?
|
||||
|
|
||||
|
[DisableConventionalRegistration] |
||||
|
public class MultiTenantConnectionStringResolver : DefaultConnectionStringResolver |
||||
|
{ |
||||
|
private readonly IMultiTenancyManager _multiTenancyManager; |
||||
|
private readonly ITenantConnectionStringStore _tenantConnectionStringStore; |
||||
|
|
||||
|
public MultiTenantConnectionStringResolver( |
||||
|
IOptions<DbConnectionOptions> options, |
||||
|
IMultiTenancyManager multiTenancyManager, |
||||
|
ITenantConnectionStringStore tenantConnectionStringStore) |
||||
|
: base(options) |
||||
|
{ |
||||
|
_multiTenancyManager = multiTenancyManager; |
||||
|
_tenantConnectionStringStore = tenantConnectionStringStore; |
||||
|
} |
||||
|
|
||||
|
public override string Resolve(string databaseName = null) |
||||
|
{ |
||||
|
var tenant = _multiTenancyManager.CurrentTenant; |
||||
|
if (tenant == null) |
||||
|
{ |
||||
|
return base.Resolve(databaseName); |
||||
|
} |
||||
|
|
||||
|
var connectionString = _tenantConnectionStringStore.GetConnectionStringOrNull(tenant.Id, databaseName); |
||||
|
if (connectionString == null) |
||||
|
{ |
||||
|
return base.Resolve(databaseName); |
||||
|
} |
||||
|
|
||||
|
return connectionString; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Volo.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Data.MultiTenancy |
||||
|
{ |
||||
|
public sealed class NullTenantConnectionStringStore : ITenantConnectionStringStore, ISingletonDependency |
||||
|
{ |
||||
|
public string GetConnectionStringOrNull(string tenantId, string databaseName) |
||||
|
{ |
||||
|
//No tenant specific connection string by default
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,95 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.Data.MultiTenancy |
||||
|
{ |
||||
|
public class MultiTenantConnectionStringResolver_Tests : MultiTenancyTestBase |
||||
|
{ |
||||
|
private readonly IMultiTenancyManager _multiTenancyManager; |
||||
|
private readonly IConnectionStringResolver _connectionResolver; |
||||
|
|
||||
|
public MultiTenantConnectionStringResolver_Tests() |
||||
|
{ |
||||
|
_multiTenancyManager = ServiceProvider.GetRequiredService<IMultiTenancyManager>(); |
||||
|
|
||||
|
_connectionResolver = ServiceProvider.GetRequiredService<IConnectionStringResolver>(); |
||||
|
_connectionResolver.ShouldBeOfType<MultiTenantConnectionStringResolver>(); |
||||
|
} |
||||
|
|
||||
|
protected override void BeforeAddApplication(IServiceCollection services) |
||||
|
{ |
||||
|
services.Configure<DbConnectionOptions>(options => |
||||
|
{ |
||||
|
options.ConnectionStrings.Default = "default-value"; |
||||
|
options.ConnectionStrings["db1"] = "db1-default-value"; |
||||
|
options.ConnectionStrings["tenant1#Default"] = "tenant1-default-value"; |
||||
|
options.ConnectionStrings["tenant1#db1"] = "tenant1-db1-value"; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
protected override void AfterAddApplication(IServiceCollection services) |
||||
|
{ |
||||
|
services.Replace(ServiceDescriptor.Transient<ITenantConnectionStringStore, MyTenantConnectionStringStore>()); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void All_Tests() |
||||
|
{ |
||||
|
//No tenant in current context
|
||||
|
_connectionResolver.Resolve().ShouldBe("default-value"); |
||||
|
_connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); |
||||
|
|
||||
|
//Overrided connection strings for tenant1
|
||||
|
using (_multiTenancyManager.ChangeTenant(new TenantInfo("tenant1"))) |
||||
|
{ |
||||
|
_connectionResolver.Resolve().ShouldBe("tenant1-default-value"); |
||||
|
_connectionResolver.Resolve("db1").ShouldBe("tenant1-db1-value"); |
||||
|
} |
||||
|
|
||||
|
//No tenant in current context
|
||||
|
_connectionResolver.Resolve().ShouldBe("default-value"); |
||||
|
_connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); |
||||
|
|
||||
|
//Undefined connection strings for tenant2
|
||||
|
using (_multiTenancyManager.ChangeTenant(new TenantInfo("tenant2"))) |
||||
|
{ |
||||
|
_connectionResolver.Resolve().ShouldBe("default-value"); |
||||
|
_connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class MyTenantConnectionStringStore : ITenantConnectionStringStore |
||||
|
{ |
||||
|
private readonly IOptions<DbConnectionOptions> _options; |
||||
|
|
||||
|
public MyTenantConnectionStringStore(IOptions<DbConnectionOptions> options) |
||||
|
{ |
||||
|
_options = options; |
||||
|
} |
||||
|
|
||||
|
public string GetConnectionStringOrNull(string tenantId, string databaseName) |
||||
|
{ |
||||
|
if (databaseName != null) |
||||
|
{ |
||||
|
if (_options.Value.ConnectionStrings.ContainsKey(tenantId + "#" + databaseName)) |
||||
|
{ |
||||
|
return _options.Value.ConnectionStrings[tenantId + "#" + databaseName]; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (_options.Value.ConnectionStrings.ContainsKey(tenantId + "#Default")) |
||||
|
{ |
||||
|
return _options.Value.ConnectionStrings[tenantId + "#Default"]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue