Изменить соединение DbContext во время выполнения

У меня есть 3 БД, с которыми я хочу работать: A,B и C. Каждая из них имеет одинаковые таблицы (например, пользователи, продукты).

Я хочу позволить пользователю решать (во время выполнения), с какой БД он хочет работать. Итак... Я использовал EF5 и создал 3 файла edbx, которые создали следующие классы: ADBEntities, BDBEntities и CDBEntities.

Как я могу позволить ему выбрать выбранную базу данных, чтобы я мог получить ее пользователей?

Я имею в виду,

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

Я думал об использовании рефлексии / базового класса (DBEntities), но не ушел далеко от этих идей.

3 ответа

Решение

Немного запоздалый ответ, но я думаю, что есть потенциальный способ сделать это с помощью аккуратного метода расширения. Как говорит slypete (хорошее имя:-)), вам нужна только ОДНА модель класса, при условии, что все таблицы / свойства идентичны. В этом случае мы можем воспользоваться соглашением EF над конфигурацией и несколькими небольшими вызовами инфраструктуры.

В любом случае, без лишних слов, закомментированный код и пример использования:

класс метода расширения:

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
        }
    }
}

использование:

// 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
    );

В настоящее время я использую это как раз для той цели, о которой вы упомянули выше, и до сих пор это мне очень помогло. Надеюсь, это поможет в вашем случае.

Передайте соответствующую строку соединения / имя соединения при создании 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 == "someemail@google.ca").Single();
} 
var defaultString = _myContext.Database.GetDbConnection().ConnectionString;
_myContext.Database.GetDbConnection().ConnectionString ="new connection" or _myContext.Database.GetDbConnection().ChangeDatabase()
//your query..
_myContext.Database.GetDbConnection().ConnectionString = defaultString;

Предполагая, что базы данных идентичны, вам просто нужно использовать один из сгенерированных классов. Вам не нужны все три (потому что они идентичны). Итак, давайте выберем один - скажем, ADBEntities,

Теперь вам нужно позволить ей выбрать соединение (строку подключения) во время выполнения. Если у вас есть три строки подключения, которые хранятся в вашем app.config/web.config, вы можете загрузить их во время выполнения, используя ConfigurationManager:

var connections = ConfigurationManager.ConnectionStrings;

Представьте варианты и выберите один из них:

foreach (ConnectionStringSettings connection in connections)
    //display connection.Name

ConnectionStringSettings selected_connection = connections[1];

Один из DBContextконструкторы принимают строку подключения, поэтому просто передайте выбранную пользователем строку подключения в конструктор ADBEntities:

using (var selecteddb = new ADBEntities(selected_connection.ConnectionString))
{
    var dstuff = from user in selecteddb.users
         where user.UserEmail == userEmail
         select user.UserID;
} 
Другие вопросы по тегам