Base solution for your next web application
Open Closed

Change the connectionstring programmatically #480


User avatar
0
hussein created

I want the system to decide which database to connect while running time based on some logic after user login. So, how to set the connectionstring programmatically?

Thanks


7 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Just set it on your DbContext. Your dbcontext should be something like that:

    public class AbpProjectNameDbContext : AbpDbContext
        {
            //...
    
            /* NOTE: 
             *   Setting "Default" to base class helps us when working migration commands on Package Manager Console.
             *   But it may cause problems when working Migrate.exe of EF. If you will apply migrations on command line, do not
             *   pass connection string name to base classes. ABP works either way.
             */
            public AbpProjectNameDbContext()
                : base("Default")
            {
    
            }
    
            /* NOTE:
             *   This constructor is used by ABP to pass connection string defined in AbpProjectNameDataModule.PreInitialize.
             *   Notice that, actually you will not directly create an instance of AbpProjectNameDbContext since ABP automatically handles it.
             */
            public AbpProjectNameDbContext(string nameOrConnectionString)
                : base(nameOrConnectionString)
            {
    
            }
        }
    

    Second constructor is called by ABP. You can dynamically select connection string here.

    public AbpProjectNameDbContext(string nameOrConnectionString)
                : base(GetDynamicConnectionString())
    

    So, create a GetDynamicConnectionString() and implement your own logic to return a connection string.

  • User Avatar
    0
    hussein created

    Thanks hikalkan for the reply,

    what i'm doing now is multi-tenancy application but using more than database not one database and a tenant id for each record.

    I have a login database and when user login i get his database name which the system should connect to, so i want from the AccountController to pass the database name to my DbContext. How can i do that ?

    Thanks

  • User Avatar
    0
    hikalkan created
    Support Team

    AccountController can not pass connection string to dbcontext. If it could, that was not enough. What about next requests for the user?

    One solution: Store connection strings (by tenant id) in a cache. Then in dbcontext, get connection string from this cache. You can get AbpSession.TenantId in DbContext. Note-1: To get connection string by tenant-id, you may not use DbContext (this causes recursive calls), but you can use old style AdoNet. Note-2: Maybe you need to 2 DbContext; one per tenants, one for host. Because there are 2 different db actually.

    Anyway, I haven't thought too much. Please share your experiences after trying it.

  • User Avatar
    0
    hussein created

    Thanks hikalkan,

    i already used 2 DbContexts one for the login information and tenant data and the other one for each instance data.

    when user login he can access the first DbContext and get his tenant database name and then i want to pass this database name to the other DbContext to set the its connectionstring.

    i want to use TenantId that in the second DbContext to pass the tenant-id throught it but i don't know how to set the TenantId inside AbpSession?

  • User Avatar
    0
    hikalkan created
    Support Team

    Are you using module-zero? If so, you can get AbpSession.TenantId inside dbcontext.

  • User Avatar
    0
    hussein created

    No, i'm using ASP.NET Boilerplate Framework and TenantId or UserId are always Null.

    How to set values for TenantId or UserId ?

  • User Avatar
    0
    hikalkan created
    Support Team

    You have 2 options to make AbpSession working:

    • You can implement IAbpSession or inherit from ClaimsAbpSession(<a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/blob/master/src/Abp/Runtime/Session/ClaimsAbpSession.cs">https://github.com/aspnetboilerplate/as ... Session.cs</a>) in your application (do not forget to register it to IOC: <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Dependency-Injection#DocHelperInterfaces">http://www.aspnetboilerplate.com/Pages/ ... Interfaces</a>). Thus, you can get/set it from any source you want.
    • Default implementation (new in v0.7.4: ClaimsAbpSession) uses Thread.CurrentPrincipal to get UserId and TenantId. So, you can set these Claims for your application (search web to understand where to set claims in AspNet).