DbPerTenantConnectionStringResolver.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. using Abp.Configuration.Startup;
  2. using Abp.Domain.Uow;
  3. using Abp.Extensions;
  4. using Abp.Runtime.Session;
  5. using VberZero.MultiTenancy;
  6. using VberZero.Session;
  7. namespace VberZero.EntityFramework;
  8. /// <summary>
  9. /// Implements <see cref="IDbPerTenantConnectionStringResolver"/> to dynamically resolve
  10. /// connection string for a multi tenant application.
  11. /// </summary>
  12. public class DbPerTenantConnectionStringResolver : DefaultConnectionStringResolver, IDbPerTenantConnectionStringResolver
  13. {
  14. /// <summary>
  15. /// Reference to the session.
  16. /// </summary>
  17. public IVzSession AbpSession { get; set; }
  18. private readonly ICurrentUnitOfWorkProvider _currentUnitOfWorkProvider;
  19. private readonly ITenantCache _tenantCache;
  20. /// <summary>
  21. /// Initializes a new instance of the <see cref="DbPerTenantConnectionStringResolver"/> class.
  22. /// </summary>
  23. public DbPerTenantConnectionStringResolver(
  24. IAbpStartupConfiguration configuration,
  25. ICurrentUnitOfWorkProvider currentUnitOfWorkProvider,
  26. ITenantCache tenantCache)
  27. : base(configuration)
  28. {
  29. _currentUnitOfWorkProvider = currentUnitOfWorkProvider;
  30. _tenantCache = tenantCache;
  31. AbpSession = NullVzSession.Instance;
  32. }
  33. public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
  34. {
  35. if (args.MultiTenancySide == Abp.MultiTenancy.MultiTenancySides.Host)
  36. {
  37. return GetNameOrConnectionString(new DbPerTenantConnectionStringResolveArgs(null, args));
  38. }
  39. return GetNameOrConnectionString(new DbPerTenantConnectionStringResolveArgs(GetCurrentTenantId(), args));
  40. }
  41. public virtual string GetNameOrConnectionString(DbPerTenantConnectionStringResolveArgs args)
  42. {
  43. if (args.TenantId == null)
  44. {
  45. //Requested for host
  46. return base.GetNameOrConnectionString(args);
  47. }
  48. var tenantCacheItem = _tenantCache.Get(args.TenantId.Value);
  49. if (tenantCacheItem.ConnectionString.IsNullOrEmpty())
  50. {
  51. //Tenant has not dedicated database
  52. return base.GetNameOrConnectionString(args);
  53. }
  54. return tenantCacheItem.ConnectionString;
  55. }
  56. public override async Task<string> GetNameOrConnectionStringAsync(ConnectionStringResolveArgs args)
  57. {
  58. if (args.MultiTenancySide == Abp.MultiTenancy.MultiTenancySides.Host)
  59. {
  60. return await GetNameOrConnectionStringAsync(new DbPerTenantConnectionStringResolveArgs(null, args));
  61. }
  62. return await GetNameOrConnectionStringAsync(new DbPerTenantConnectionStringResolveArgs(GetCurrentTenantId(), args));
  63. }
  64. public virtual async Task<string> GetNameOrConnectionStringAsync(DbPerTenantConnectionStringResolveArgs args)
  65. {
  66. if (args.TenantId == null)
  67. {
  68. //Requested for host
  69. return await base.GetNameOrConnectionStringAsync(args);
  70. }
  71. var tenantCacheItem = await _tenantCache.GetAsync(args.TenantId.Value);
  72. if (tenantCacheItem.ConnectionString.IsNullOrEmpty())
  73. {
  74. //Tenant has not dedicated database
  75. return await base.GetNameOrConnectionStringAsync(args);
  76. }
  77. return tenantCacheItem.ConnectionString;
  78. }
  79. protected virtual int? GetCurrentTenantId()
  80. {
  81. return _currentUnitOfWorkProvider.Current != null
  82. ? _currentUnitOfWorkProvider.Current.GetTenantId()
  83. : AbpSession.TenantId;
  84. }
  85. }