Browse Source

Merged IMultiTenancyManager with ICurrentTenant

pull/191/head
Halil İbrahim Kalkan 9 years ago
parent
commit
6f6fcfb798
  1. 1
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  2. 36
      src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentTenant.cs
  3. 17
      src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ICurrentTenant.cs
  4. 15
      src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IMultiTenancyManager.cs
  5. 16
      src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantScopeProvider.cs
  6. 18
      src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/MultiTenancyManagerCurrentTenant.cs
  7. 16
      src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs
  8. 12
      src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/NullCurrentTenant.cs
  9. 8
      src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantScopeProvider.cs
  10. 4
      test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/App/AppModule.cs
  11. 8
      test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/Data/MultiTenancy/MultiTenantConnectionStringResolver_Tests.cs
  12. 44
      test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/MultiTenancy/CurrentTenant_Tests.cs

1
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -37,7 +37,6 @@ namespace Volo.Abp.EntityFrameworkCore
: base(options) : base(options)
{ {
GuidGenerator = SimpleGuidGenerator.Instance; GuidGenerator = SimpleGuidGenerator.Instance;
CurrentTenant = NullCurrentTenant.Instance;
} }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)

36
src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/MultiTenancyManager.cs → src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentTenant.cs

@ -1,24 +1,30 @@
using System; using System;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy namespace Volo.Abp.MultiTenancy
{ {
//TODO: This is very similar to ITenantScopeProvider. Consider to unify them! public class CurrentTenant : ICurrentTenant, ITransientDependency
public class MultiTenancyManager : IMultiTenancyManager, ITransientDependency
{ {
public TenantInfo CurrentTenant => GetCurrentTenant(); public bool IsAvailable => Id.HasValue;
public Guid? Id => GetCurrentTenant()?.Id;
public string Name => GetCurrentTenant()?.Name;
public ConnectionStrings ConnectionStrings => GetCurrentTenant()?.ConnectionStrings;
private readonly ITenantScopeProvider _tenantScopeProvider; private readonly TenantScopeProvider _tenantScopeProvider;
private readonly ITenantStore _tenantStore; private readonly ITenantStore _tenantStore;
private readonly ILogger<MultiTenancyManager> _logger; private readonly ILogger<CurrentTenant> _logger;
private readonly ITenantResolver _tenantResolver; private readonly ITenantResolver _tenantResolver;
public MultiTenancyManager( public CurrentTenant(
ITenantScopeProvider tenantScopeProvider, TenantScopeProvider tenantScopeProvider,
ITenantStore tenantStore, ITenantStore tenantStore,
ILogger<MultiTenancyManager> logger, ILogger<CurrentTenant> logger,
ITenantResolver tenantResolver) ITenantResolver tenantResolver)
{ {
_tenantScopeProvider = tenantScopeProvider; _tenantScopeProvider = tenantScopeProvider;
@ -27,23 +33,23 @@ namespace Volo.Abp.MultiTenancy
_tenantResolver = tenantResolver; _tenantResolver = tenantResolver;
} }
public IDisposable ChangeTenant(Guid? tenantId) public IDisposable Change(Guid? id)
{ {
if (tenantId == null) if (id == null)
{ {
return _tenantScopeProvider.EnterScope(null); return _tenantScopeProvider.EnterScope(null);
} }
var tenant = _tenantStore.Find(tenantId.Value); var tenant = _tenantStore.Find(id.Value);
if (tenant == null) if (tenant == null)
{ {
throw new AbpException("There is no tenant with given tenant id: " + tenantId.Value); throw new AbpException("There is no tenant with given tenant id: " + id.Value);
} }
return _tenantScopeProvider.EnterScope(tenant); return _tenantScopeProvider.EnterScope(tenant);
} }
public IDisposable ChangeTenant(string name) public IDisposable Change(string name)
{ {
if (name == null) if (name == null)
{ {
@ -59,6 +65,7 @@ namespace Volo.Abp.MultiTenancy
return _tenantScopeProvider.EnterScope(tenant); return _tenantScopeProvider.EnterScope(tenant);
} }
[CanBeNull]
protected virtual TenantInfo GetCurrentTenant() protected virtual TenantInfo GetCurrentTenant()
{ {
if (_tenantScopeProvider.CurrentScope != null) if (_tenantScopeProvider.CurrentScope != null)
@ -71,6 +78,7 @@ namespace Volo.Abp.MultiTenancy
return ResolveTenant(); return ResolveTenant();
} }
[CanBeNull]
protected virtual TenantInfo ResolveTenant() protected virtual TenantInfo ResolveTenant()
{ {
var tenantIdOrName = _tenantResolver.ResolveTenantIdOrName(); var tenantIdOrName = _tenantResolver.ResolveTenantIdOrName();

17
src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ICurrentTenant.cs

@ -1,9 +1,26 @@
using System; using System;
using JetBrains.Annotations;
using Volo.Abp.Data;
namespace Volo.Abp.MultiTenancy namespace Volo.Abp.MultiTenancy
{ {
public interface ICurrentTenant public interface ICurrentTenant
{ {
bool IsAvailable { get; }
[CanBeNull]
Guid? Id { get; } Guid? Id { get; }
[CanBeNull]
string Name { get; }
[CanBeNull]
ConnectionStrings ConnectionStrings { get; }
[NotNull]
IDisposable Change(Guid? id);
[NotNull]
IDisposable Change([CanBeNull] string name);
} }
} }

15
src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IMultiTenancyManager.cs

@ -1,15 +0,0 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy
{
public interface IMultiTenancyManager
{
[CanBeNull]
TenantInfo CurrentTenant { get; }
IDisposable ChangeTenant(Guid? tenantId);
IDisposable ChangeTenant([CanBeNull] string name);
}
}

16
src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantScopeProvider.cs

@ -1,16 +0,0 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy
{
public interface ITenantScopeProvider
{
/// <summary>
/// Can be null for host.
/// </summary>
[CanBeNull]
TenantScope CurrentScope { get; }
IDisposable EnterScope([CanBeNull] TenantInfo tenant);
}
}

18
src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/MultiTenancyManagerCurrentTenant.cs

@ -1,18 +0,0 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
[Dependency(ReplaceServices = true)]
public class MultiTenancyManagerCurrentTenant : ICurrentTenant, ITransientDependency
{
public Guid? Id => _multiTenancyManager.CurrentTenant?.Id;
private readonly IMultiTenancyManager _multiTenancyManager;
public MultiTenancyManagerCurrentTenant(IMultiTenancyManager multiTenancyManager)
{
_multiTenancyManager = multiTenancyManager;
}
}
}

16
src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs

@ -8,22 +8,22 @@ namespace Volo.Abp.MultiTenancy
[Dependency(ReplaceServices = true)] [Dependency(ReplaceServices = true)]
public class MultiTenantConnectionStringResolver : DefaultConnectionStringResolver public class MultiTenantConnectionStringResolver : DefaultConnectionStringResolver
{ {
private readonly IMultiTenancyManager _multiTenancyManager; private readonly ICurrentTenant _currentTenant;
public MultiTenantConnectionStringResolver( public MultiTenantConnectionStringResolver(
IOptionsSnapshot<DbConnectionOptions> options, IOptionsSnapshot<DbConnectionOptions> options,
IMultiTenancyManager multiTenancyManager) ICurrentTenant currentTenant)
: base(options) : base(options)
{ {
_multiTenancyManager = multiTenancyManager; _currentTenant = currentTenant;
} }
public override string Resolve(string connectionStringName = null) public override string Resolve(string connectionStringName = null)
{ {
var tenant = _multiTenancyManager.CurrentTenant; var tenantConnectionStrings = _currentTenant.ConnectionStrings;
//No current tenant, fallback to default logic //No current tenant, fallback to default logic
if (tenant == null) if (tenantConnectionStrings == null)
{ {
return base.Resolve(connectionStringName); return base.Resolve(connectionStringName);
} }
@ -31,12 +31,12 @@ namespace Volo.Abp.MultiTenancy
//Requesting default connection string //Requesting default connection string
if (connectionStringName == null) if (connectionStringName == null)
{ {
return tenant.ConnectionStrings.Default ?? return tenantConnectionStrings.Default ??
Options.ConnectionStrings.Default; Options.ConnectionStrings.Default;
} }
//Requesting specific connection string //Requesting specific connection string
var connString = tenant.ConnectionStrings.GetOrDefault(connectionStringName); var connString = tenantConnectionStrings.GetOrDefault(connectionStringName);
if (connString != null) if (connString != null)
{ {
return connString; return connString;
@ -53,7 +53,7 @@ namespace Volo.Abp.MultiTenancy
return connStringInOptions; return connStringInOptions;
} }
return tenant.ConnectionStrings.Default ?? return tenantConnectionStrings.Default ??
Options.ConnectionStrings.Default; Options.ConnectionStrings.Default;
} }
} }

12
src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/NullCurrentTenant.cs

@ -1,12 +0,0 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class NullCurrentTenant : ICurrentTenant, ISingletonDependency
{
public static NullCurrentTenant Instance { get; } = new NullCurrentTenant();
public Guid? Id { get; } = null;
}
}

8
src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AsyncLocalTenantScopeProvider.cs → src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantScopeProvider.cs

@ -4,17 +4,17 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy namespace Volo.Abp.MultiTenancy
{ {
public class AsyncLocalTenantScopeProvider : ITenantScopeProvider, ISingletonDependency public class TenantScopeProvider : ISingletonDependency
{ {
public TenantScope CurrentScope public TenantScope CurrentScope
{ {
get { return _currentScope.Value; } get => _currentScope.Value;
private set { _currentScope.Value = value; } private set => _currentScope.Value = value;
} }
private readonly AsyncLocal<TenantScope> _currentScope; private readonly AsyncLocal<TenantScope> _currentScope;
public AsyncLocalTenantScopeProvider() public TenantScopeProvider()
{ {
_currentScope = new AsyncLocal<TenantScope>(); _currentScope = new AsyncLocal<TenantScope>();
} }

4
test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/App/AppModule.cs

@ -32,12 +32,12 @@ namespace Volo.Abp.AspNetCore.App
app.Run(async (ctx) => app.Run(async (ctx) =>
{ {
var manager = ctx.RequestServices.GetRequiredService<IMultiTenancyManager>(); var currentTenant = ctx.RequestServices.GetRequiredService<ICurrentTenant>();
var jsonSerializer = ctx.RequestServices.GetRequiredService<IJsonSerializer>(); var jsonSerializer = ctx.RequestServices.GetRequiredService<IJsonSerializer>();
var dictionary = new Dictionary<string, string> var dictionary = new Dictionary<string, string>
{ {
["TenantId"] = manager.CurrentTenant == null ? "" : manager.CurrentTenant.Id.ToString() ["TenantId"] = currentTenant.IsAvailable ? currentTenant.Id.ToString() : ""
}; };
var result = jsonSerializer.Serialize(dictionary, camelCase: false); var result = jsonSerializer.Serialize(dictionary, camelCase: false);

8
test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/Data/MultiTenancy/MultiTenantConnectionStringResolver_Tests.cs

@ -9,12 +9,12 @@ namespace Volo.Abp.Data.MultiTenancy
{ {
public class MultiTenantConnectionStringResolver_Tests : MultiTenancyTestBase public class MultiTenantConnectionStringResolver_Tests : MultiTenancyTestBase
{ {
private readonly IMultiTenancyManager _multiTenancyManager; private readonly ICurrentTenant _currentTenant;
private readonly IConnectionStringResolver _connectionResolver; private readonly IConnectionStringResolver _connectionResolver;
public MultiTenantConnectionStringResolver_Tests() public MultiTenantConnectionStringResolver_Tests()
{ {
_multiTenancyManager = ServiceProvider.GetRequiredService<IMultiTenancyManager>(); _currentTenant = ServiceProvider.GetRequiredService<ICurrentTenant>();
_connectionResolver = ServiceProvider.GetRequiredService<IConnectionStringResolver>(); _connectionResolver = ServiceProvider.GetRequiredService<IConnectionStringResolver>();
_connectionResolver.ShouldBeOfType<MultiTenantConnectionStringResolver>(); _connectionResolver.ShouldBeOfType<MultiTenantConnectionStringResolver>();
@ -53,7 +53,7 @@ namespace Volo.Abp.Data.MultiTenancy
_connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); _connectionResolver.Resolve("db1").ShouldBe("db1-default-value");
//Overrided connection strings for tenant1 //Overrided connection strings for tenant1
using (_multiTenancyManager.ChangeTenant("tenant1")) using (_currentTenant.Change("tenant1"))
{ {
_connectionResolver.Resolve().ShouldBe("tenant1-default-value"); _connectionResolver.Resolve().ShouldBe("tenant1-default-value");
_connectionResolver.Resolve("db1").ShouldBe("tenant1-db1-value"); _connectionResolver.Resolve("db1").ShouldBe("tenant1-db1-value");
@ -64,7 +64,7 @@ namespace Volo.Abp.Data.MultiTenancy
_connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); _connectionResolver.Resolve("db1").ShouldBe("db1-default-value");
//Undefined connection strings for tenant2 //Undefined connection strings for tenant2
using (_multiTenancyManager.ChangeTenant("tenant2")) using (_currentTenant.Change("tenant2"))
{ {
_connectionResolver.Resolve().ShouldBe("default-value"); _connectionResolver.Resolve().ShouldBe("default-value");
_connectionResolver.Resolve("db1").ShouldBe("db1-default-value"); _connectionResolver.Resolve("db1").ShouldBe("db1-default-value");

44
test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/MultiTenancy/MultiTenantManager_Tests.cs → test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/MultiTenancy/CurrentTenant_Tests.cs

@ -6,17 +6,17 @@ using Xunit;
namespace Volo.Abp.MultiTenancy namespace Volo.Abp.MultiTenancy
{ {
public class MultiTenantManager_Tests : MultiTenancyTestBase public class CurrentTenant_Tests : MultiTenancyTestBase
{ {
private readonly IMultiTenancyManager _multiTenancyManager; private readonly ICurrentTenant _currentTenant;
private readonly string _tenantA = "A"; private readonly string _tenantA = "A";
private readonly string _tenantB = "B"; private readonly string _tenantB = "B";
private string _tenantToBeResolved; private string _tenantToBeResolved;
public MultiTenantManager_Tests() public CurrentTenant_Tests()
{ {
_multiTenancyManager = ServiceProvider.GetRequiredService<IMultiTenancyManager>(); _currentTenant = ServiceProvider.GetRequiredService<ICurrentTenant>();
} }
[Fact] [Fact]
@ -24,7 +24,7 @@ namespace Volo.Abp.MultiTenancy
{ {
//Assert //Assert
_multiTenancyManager.CurrentTenant.ShouldBeNull(); _currentTenant.Id.ShouldBeNull();
} }
protected override void BeforeAddApplication(IServiceCollection services) protected override void BeforeAddApplication(IServiceCollection services)
@ -70,8 +70,8 @@ namespace Volo.Abp.MultiTenancy
//Assert //Assert
Assert.NotNull(_multiTenancyManager.CurrentTenant); Assert.NotNull(_currentTenant.Id);
_multiTenancyManager.CurrentTenant.Name.ShouldBe(_tenantA); _currentTenant.Name.ShouldBe(_tenantA);
} }
[Fact] [Fact]
@ -83,37 +83,37 @@ namespace Volo.Abp.MultiTenancy
//Assert //Assert
Assert.NotNull(_multiTenancyManager.CurrentTenant); Assert.NotNull(_currentTenant.Id);
_multiTenancyManager.CurrentTenant.Name.ShouldBe(_tenantB); _currentTenant.Name.ShouldBe(_tenantB);
} }
[Fact] [Fact]
public void Should_Get_Changed_Tenant_If_Wanted() public void Should_Get_Changed_Tenant_If_Wanted()
{ {
_multiTenancyManager.CurrentTenant.ShouldBe(null); _currentTenant.Id.ShouldBe(null);
_tenantToBeResolved = _tenantB; _tenantToBeResolved = _tenantB;
Assert.NotNull(_multiTenancyManager.CurrentTenant); Assert.NotNull(_currentTenant.Id);
_multiTenancyManager.CurrentTenant.Name.ShouldBe(_tenantB); _currentTenant.Name.ShouldBe(_tenantB);
using (_multiTenancyManager.ChangeTenant(_tenantA)) using (_currentTenant.Change(_tenantA))
{ {
Assert.NotNull(_multiTenancyManager.CurrentTenant); Assert.NotNull(_currentTenant.Id);
_multiTenancyManager.CurrentTenant.Name.ShouldBe(_tenantA); _currentTenant.Name.ShouldBe(_tenantA);
using (_multiTenancyManager.ChangeTenant(_tenantB)) using (_currentTenant.Change(_tenantB))
{ {
Assert.NotNull(_multiTenancyManager.CurrentTenant); Assert.NotNull(_currentTenant.Id);
_multiTenancyManager.CurrentTenant.Name.ShouldBe(_tenantB); _currentTenant.Name.ShouldBe(_tenantB);
} }
Assert.NotNull(_multiTenancyManager.CurrentTenant); Assert.NotNull(_currentTenant.Id);
_multiTenancyManager.CurrentTenant.Name.ShouldBe(_tenantA); _currentTenant.Name.ShouldBe(_tenantA);
} }
Assert.NotNull(_multiTenancyManager.CurrentTenant); Assert.NotNull(_currentTenant.Id);
_multiTenancyManager.CurrentTenant.Name.ShouldBe(_tenantB); _currentTenant.Name.ShouldBe(_tenantB);
} }
} }
} }
Loading…
Cancel
Save