Open Closed

Override Connection String For Tenant #5175


User avatar
0
jpatron created
  • ABP Framework version: v6.0.3
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): yes
  • Exception message and stack trace: N/A
  • Steps to reproduce the issue:" N/A

Hello,

I created a setting to determine whether the tenant should use a specific connection string to a database with real data or another connection string that points to a "demo" database. I followed the idea of overwriting the connection string by calling a method under ConfigureServices in our web application module as suggested by the following link: https://docs.abp.io/en/abp/6.0/Connection-Strings However, if I try to get the ISettingsManager at that point, it is always null. I have also tried getting IServiceProvider and ServiceProvider with the same unsuccessful results. Here is the method I am using to accomplish this task:

private async Task ConfigureDemo(ServiceConfigurationContext context, IConfiguration configuration)
    {
        var settingProvider = context.Services.GetObjectOrNull<ISettingManager>();
        if (settingProvider != null)
        {
            var useDemoDb = await settingProvider.GetOrNullForCurrentTenantAsync(<Our_App>Settings.UseDemo);
            if (useDemoDb.Equals("True", StringComparison.OrdinalIgnoreCase))
            {
                Configure<AbpDbConnectionOptions>(options =>
                {
                    options.ConnectionStrings["RealDataDb"] = configuration.GetConnectionString("DemoDb");
                });
            }
        }
    }

Do you have any ideas or suggestions on how we can solve this problem? Thanks in advance!


5 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    You can consider to replace the Connection String Resolver https://docs.abp.io/en/abp/6.0/Connection-Strings#replace-the-connection-string-resolver

  • User Avatar
    0
    jpatron created

    Hi,

    I have created a CustomConnectionStringResolver as you suggested, but now I have a follow-up question. The Default connection is stored in the host database for each tenant. However, the connection I am trying to overwrite is stored in appsettings.json, not in the host database. When I debug into the ResolveAsync method of my CustomConnectionStringResolver, it doesn't seem to find the connection I am looking for. Here is my updated ResolveAsync method:

    public override async Task<string> ResolveAsync(string connectionStringName = null)
    {
        if (_currentUser.IsAuthenticated && _currentTenant.Id != null)
        {
            var useDemo = await _settingManager.GetOrNullForCurrentTenantAsync(AppSettings.UseDemo);
            if (useDemo?.Equals("True", StringComparison.OrdinalIgnoreCase) == true
                && connectionStringName != null
                && connectionStringName == "RealDataDb")
            {
                var connectionString = _configuration.GetConnectionString("DemoDb");
                if (!connectionString.IsNullOrWhiteSpace())
                {
                    return connectionString;
                }
            }
        }
    
        return await base.ResolveAsync(connectionStringName);
    }
    

    Both "RealDataDb" and "DemoDb" connection strings are stored in appsettings.json. Can I still use this method to decide which connection to use depending on the value of the useDemo setting?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    I think this way should work.

    You also need to override the Resolve method.

    BTW, you can share a project that can reproduce the problem with me if it's still not working for you. shiwei.liang@volosoft.com I will check it.

  • User Avatar
    0
    jpatron created

    Hi,

    I managed to accomplish the connection change. However, we are using a distributed cache for the entities within the "RealDataDb" context. Is there a way to reset the distributed cache for those entities, or remove them from the cache? Also, I noticed that this method gets called pretty frequently, is that expected?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Is there a way to reset the distributed cache for those entities, or remove them from the cache?

    You need to manually remove the bold change using the code:

    IDistributedCache<....> cache;
    
    cache.RemoveAsync();
    cache.RemoveManyAsync()
    

    Also, I noticed that this method gets called pretty frequently, is that expected?

    Yes.

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11