0

I'm developing a web application in asp.net mvc. My application uses multiple databases. The database on which working on depends by the logged user. I manage login on two levels:

  • Level1 on a "master" database where I have info about the login username/email and the "specific" database to use.
  • Level2 on the "specific" database where I manage users and roles with Identity2.

Example: In the "master" database I have a record in User table with: - username = user1 - databaseToUse = "specificDb1"

In the "specific" database called specificDb1, for the same user, I have a record in User table with all I need to manage user authentication and more.

What I want to achieve is:

  1. Start the website, click on login, insert username and password, click on login.
  2. Search for the username in the master database, if exist get the specific database name associated to the user.
  3. Set here, DYNAMICALLY, the connection string for the "specific" database and perform Identity 2 login operations.

No problems for points 1 and 2. The problem is in point 3. I use EntityFramework 6 Code First for both (master and specific) databases.

Regarding the configuration part of Identity I see in Startup.Auth.cs:

        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

Should I change something in Identity configuration?

Thanks in advance.

Steve Greene
  • 12,029
  • 1
  • 33
  • 54
jacktric
  • 393
  • 3
  • 14

1 Answers1

5

After hours spent in searching here my personal (maybe not the best) working solution.

In the Login action of AccountController, after the first check in "master" database, set the "specific" database informations in Session scope:

//Save the database infos in Session.
Session.Add("SqlServerInstance", masterUser.Company.DatabaseServer);
Session.Add("DbName", masterUser.Company.DatabaseName);

Always in AccountController update the SignInManager and UserManager properties fixing the connection string for the Identity context:

public ApplicationSignInManager SignInManager
    {
        get
        {
            //Set manually the right connection string used by the Identity database context.
            HttpContext.GetOwinContext().Get<ApplicationDbContext>().Database.Connection.ConnectionString = ApplicationDbContext.GetConnectionString();

            return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
        }
        private set
        {
            _signInManager = value;
        }
    }

    public ApplicationUserManager UserManager
    {
        get
        {
            //Set manually the right connection string used by the Identity database context.
            HttpContext.GetOwinContext().Get<ApplicationDbContext>().Database.Connection.ConnectionString = ApplicationDbContext.GetConnectionString();

            return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }

And finally the method that give us the connection string:

/// <summary>
    /// Get the connection string getting SqlServerInstance and DbName from Session.
    /// </summary>
    public static string GetConnectionString()
    {

        string sqlServerInstance = DEFAULT_SQLSERVERINSTANCE;
        if (HttpContext.Current.Session != null && HttpContext.Current.Session["SqlServerInstance"] != null)
            sqlServerInstance = Convert.ToString(HttpContext.Current.Session["SqlServerInstance"]);

        string dbName = DEFAULT_DBNAME;
        if (HttpContext.Current.Session != null && HttpContext.Current.Session["DbName"] != null)
            dbName = Convert.ToString(HttpContext.Current.Session["DbName"]);

        return "Data Source=" + sqlServerInstance + ";Initial Catalog=" + dbName + ";Integrated Security=True";

    }

Hope this can help.

jacktric
  • 393
  • 3
  • 14
  • Thank you so much for digging in the depth and for your solution. It helped me to solve a similar problem in shorter time. – peter_the_oak May 23 '18 at 07:49
  • I am using your solution but I have ran into a problem where users are logged out after the "validateInterval" is up regardless of whether they have been active on the site or not. Is this something you have experienced or found a solution for? I have asked the question on the following post if you do have an answer or any suggestions for this problem: https://stackoverflow.com/questions/55126549/dynamic-database-connection-using-asp-net-identity – WebFletch Mar 12 '19 at 22:13
  • 1
    @trfletch yes, I have experienced the same issue on my application. I'm going to post my solution on your new question. – jacktric Mar 14 '19 at 15:37