Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change DbContext connection at run-time

I have 3 DBs that I want to work with: A,B and C. each one have the same tables (for example: users, products).

I want to let the user decide (on run-time) which DB he wants to work with. So... I used EF5 and created 3 edbx files which created the following classes: ADBEntities, BDBEntities and CDBEntities.

How can I let him decide the selecteddb so I could get its users?

I mean,

var dstuff = from user in selecteddb.users
             where user.UserEmail == userEmail
             select user.UserID;

I've thought of using reflection / base class (DBEntities), but didn't get far with those ideas.

like image 993
user3017270 Avatar asked Nov 26 '13 16:11

user3017270


3 Answers

a bit late on this answer but I think there's a potential way to do this with a neat little extension method. As slypete (nice name :-)) says, you only need ONE class model, assuming all tables/properties are identical. This being the case, we can take advantage of the EF convention over configuration plus a few little framework calls.

Anyway, without further ado, the commented code and example usage:

the extension method class:

public static class ConnectionTools
{
    // all params are optional
    public static void ChangeDatabase(
        this DbContext source,
        string initialCatalog = "",
        string dataSource = "",
        string userId = "",
        string password = "",
        bool integratedSecuity = true,
        string configConnectionStringName = "") 
        /* this would be used if the
        *  connectionString name varied from 
        *  the base EF class name */
    {
        try
        {
            // use the const name if it's not null, otherwise
            // using the convention of connection string = EF contextname
            // grab the type name and we're done
            var configNameEf = string.IsNullOrEmpty(configConnectionStringName)
                ? source.GetType().Name 
                : configConnectionStringName;

            // add a reference to System.Configuration
            var entityCnxStringBuilder = new EntityConnectionStringBuilder
                (System.Configuration.ConfigurationManager
                    .ConnectionStrings[configNameEf].ConnectionString);

            // init the sqlbuilder with the full EF connectionstring cargo
            var sqlCnxStringBuilder = new SqlConnectionStringBuilder
                (entityCnxStringBuilder.ProviderConnectionString);

            // only populate parameters with values if added
            if (!string.IsNullOrEmpty(initialCatalog))
                sqlCnxStringBuilder.InitialCatalog = initialCatalog;
            if (!string.IsNullOrEmpty(dataSource))
                sqlCnxStringBuilder.DataSource = dataSource;
            if (!string.IsNullOrEmpty(userId))
                sqlCnxStringBuilder.UserID = userId;
            if (!string.IsNullOrEmpty(password))
                sqlCnxStringBuilder.Password = password;

            // set the integrated security status
            sqlCnxStringBuilder.IntegratedSecurity = integratedSecuity;

            // now flip the properties that were changed
            source.Database.Connection.ConnectionString 
                = sqlCnxStringBuilder.ConnectionString;
        }
        catch (Exception ex)
        {
            // set log item if required
        }
    }
}

usage:

// assumes a connectionString name in .config of ADBEntities
var selectedDb = new ADBEntities();
// so only reference the changed properties
// using the object parameters by name
selectedDb.ChangeDatabase
    (
        initialCatalog: "name-of-bdb-initialcatalog",
        userId: "jackthelad",
        password: "nosecrets",
        dataSource: @".\sqlexpress" // could be ip address 100.23.45.67 etc
    );

I currently use this for exactly the purpose that you mention above and thus far, it's served me very well. Hope it helps in your instance.

like image 149
jim tollan Avatar answered Oct 10 '22 08:10

jim tollan


Pass the appropriate connection string / connection name when creating a DbContext

http://msdn.microsoft.com/en-us/library/gg679467%28v=vs.113%29.aspx

using (var context = new MyDbContext("Server=localhost;Database=dbA;..."))
{
    return context.Users.Where(u => u.Email == "[email protected]").Single();
} 
like image 24
Matthew Avatar answered Oct 10 '22 08:10

Matthew


var defaultString = _myContext.Database.GetDbConnection().ConnectionString;
_myContext.Database.GetDbConnection().ConnectionString ="new connection" or _myContext.Database.GetDbConnection().ChangeDatabase()
//your query..
_myContext.Database.GetDbConnection().ConnectionString = defaultString;
like image 32
Lakmal Avatar answered Oct 10 '22 08:10

Lakmal