简体   繁体   English

如何使用C#覆盖在运行时在Web.config文件中设置的数据库?

[英]How to override the database that is set in the Web.config file at run time using C#?

I have a Context class that will accept a connection name in the constructor. 我有一个Context类,它将在构造函数中接受连接名称。 Then it allows me to connect to a specific server. 然后,它允许我连接到特定的服务器。

I would like to know how to change the default database for that connection at run time. 我想知道如何在运行时更改该连接的默认数据库。

Here is what I have done 这是我所做的

In the Web.config file I added the following connection strings 在Web.config文件中,我添加了以下连接字符串

  <connectionStrings>
    <add name="BaseConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ScripterDynamo;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\ScripterDynamo.mdf" providerName="System.Data.SqlClient" />
    <add name="conn1" connectionString="Server=Serv1;Database=db1;UserId=myUser; Password=myPassword;" providerName="System.Data.SqlClient" />
    <add name="conn2" connectionString="Server=Serv2;Database=db2;UserId=myUser; Password=myPassword;" providerName="System.Data.SqlClient" />
    <add name="conn3" connectionString="Server=Serv3;Database=db3;UserId=myUser; Password=myPassword;" providerName="System.Data.SqlClient" />
    <add name="conn4" connectionString="Server=Serv4;Database=db4;UserId=myUser; Password=myPassword;" providerName="System.Data.SqlClient" />
  </connectionStrings>

Then I create a simple context class like so 然后我创建一个像这样的简单上下文类

using ScripterEngine.Models;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using System.Data.SqlClient;
using System.Linq;
using System.Web;

namespace ScripterEngine.DataAccessLayer
{
    public class BaseContext : DbContext
    {
        public DbSet<Campaign> Campaign { get; set; }
        public DbSet<TableMeta> Campaign { get; set; }

        public BaseContext(string connectionName = "BaseConnection")
            : base(connectionName)
        {

        }
    }
}

Using this context class I can connect to conn4 like this 使用此上下文类,我可以像这样连接到conn4

BaseConnection conn4 = BaseConnection("conn4");

The only problem here is that the connection "conn4" will connect to the database called db4 which is set by default in the connection string. 唯一的问题是,连接“ conn4”将连接到名为db4的数据库,该数据库在连接字符串中默认设置。 This is expect and fine in most cases. 在大多数情况下,这是期望的并且很好。 But in my case, I want to be able to change what database to connect to at run time. 但就我而言,我希望能够在运行时更改要连接的数据库。

My question, how can I change the database on the fly? 我的问题是,如何即时更改数据库? Is there a way to add a method in the context class which will override the default database only? 有没有一种方法可以在上下文类中添加仅覆盖默认数据库的方法?

UPDATED 更新

Here is what I have changed my context class hoping that the setDatabase method will allow me to change the database at run time 这是我已更改上下文类的内容,希望setDatabase方法允许我在运行时更改数据库

using ScripterEngine.Models;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using System.Data.SqlClient;
using System.Linq;
using System.Web;

namespace ScripterEngine.DataAccessLayer
{
    public class BaseContext : DbContext
    {
        protected string connectionName;
        public DbSet<Campaign> Campaign { get; set; }
        public DbSet<TableMeta> TableMeta { get; set; }

        public BaseContext(string connName = "BaseConnection")
            : base(connName)
        {
            connectionName = connName;
        }

        public BaseContext setDatabase(string databaseName)
        {
            var connection = System.Configuration.ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;

            //change the database before creating the new connection
            return new BaseContext(connection);
        }


    }
}

I would use it like so 我会这样使用

        BaseContext db1 = new BaseContext("conn4";
        var connToNewDB = db1.setDatabase("SomeNewDatabase");

You can do something like this, this ExampleData is just an example to understand, you can acossiate the values here you need, you connection string stay something like that: 您可以执行以下操作,这个ExampleData只是一个示例,您可以在此处合并需要的值,连接字符串保持类似的状态:

<connectionStrings>
        <add name="ConnectionString.Properties.Settings.CustomConnectionString"
            connectionString="Persist Security Info=True" providerName="System.Data.SqlClient" />
    </connectionStrings>

This is just example to initialize data using System; 这只是使用System初始化数据的示例;

namespace ConnectionStringCustom
{
    public static class ExampleData
    {
        public static String connUserName = "user";
        public static String connPassword = "pass";
        public static String connServerName = "servername";
        public static String connDatabaseName = "databasename";
    }
}



namespace ConnectionStringCustom.Properties
   {

   internal sealed partial class Settings
      {


      void Settings_SettingsLoaded( object sender, System.Configuration.SettingsLoadedEventArgs e )
         {
             this["CustomConnectionString"] = "Data Source=" + ExampleData.connServerName + ";"
                                          + "Initial Catalog=" + ExampleData.connDatabaseName + ";"
                                          + "Persist Security Info=false;"
                                          + "User ID=" + ExampleData.strConnUserName + ";"
                                          + "Password=" + ExampleData.connPassword + ";";
         }

      }

   }

With this you can change all proprieties. 这样,您可以更改所有财产。

EDIT: See your changes I think probably you need something like 编辑:看到您的更改,我想您可能需要类似的东西

https://stackoverflow.com/a/7692708/5842138 https://stackoverflow.com/a/7692708/5842138

But I think is not an good practice, why you dont simply create many ConnectionStrings ? 但是我认为这不是一个好习惯,为什么不简单地创建许多ConnectionStrings?

Hope this help 希望这个帮助

Try to set DbConnection.ConnectionString property. 尝试设置DbConnection.ConnectionString属性。

dataContextInstance.Database.Connection.ConnectionString = "new connection string";

But I am not sure that you don't need to reinitialize some of your properties/code after changing connection string. 但是我不确定更改连接字符串后是否不需要重新初始化某些属性/代码。

I created a 2 contexts. 我创建了2个上下文。

  1. BaseContext: This context does not change and I use it to design my app using Code first approach. BaseContext:此上下文不会更改,我使用它来使用代码优先方法设计我的应用程序。

  2. DynamicContext: This context will change at run time. DynamicContext:此上下文将在运行时更改。

To get the DynamicContext to work, I created a dynamic connection in my connection file. 为了使DynamicContext正常工作,我在连接文件中创建了一个动态连接。

I basiclly added this to my block 我基本上将此添加到我的块中

<add name="DynamicConnection" connectionString="Server=DefaultServer;Initial Catalog=I3_IC;User ID=defaultUser; Password=defaultPassword;" providerName="System.Data.SqlClient" />

Then I created a new context class like this 然后我创建了一个像这样的新上下文类

using System; 使用系统; using System.Collections.Generic; 使用System.Collections.Generic; using System.Data.Common; 使用System.Data.Common; using System.Data.Entity; 使用System.Data.Entity; using System.Data.Entity.Core.EntityClient; 使用System.Data.Entity.Core.EntityClient; using System.Data.SqlClient; 使用System.Data.SqlClient; using System.Linq; 使用System.Linq; using System.Web; 使用System.Web;

namespace MyApp.DataAccessLayer
{
    public class DynamicContext : DbContext
    {
        protected string connectionName = "DynamicConnection";

        protected string myServerName;

        protected string myUserId;

        protected string myPassword;

        /**
         * Created the connection to the server using the giving connection string name.
         * This constructor will allow you to connect to any connection string found in the Web.config file
         * 
         * @param connName
         */
        public DynamicContext(string serverName = null, string userID = null, string password = null)
            : base("DynamicConnection")
        {
            myServerName = serverName;

            myUserId = userID;

            myPassword = password;
        }

        /**
         * This constructor will allow you to construct a context by giving a string and it can only be call from the class itself
         * 
         */
        private DynamicContext(string connectionString)
            : base(connectionString)
        {
        } 


        /**
         * Changes the default database
         * 
         * @param databaseName
         */
        public DynamicContext setDatabase(string databaseName)
        {
            //Get the existing string for dynamic connection
            var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;

            //convert the existsing string into an object
            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString);

            //change the database before creating the new connection
            builder.InitialCatalog = databaseName;

            if (myServerName != null){
                builder.DataSource = myServerName;
            }

            if (myUserId != null){
                builder.UserID = myUserId;
            }

            if (myPassword != null){
                builder.Password = myPassword;
            }

            return new DynamicContext(builder.ConnectionString);
        }

    }
}

Then I use this like so 然后我像这样使用

//Create a dynamic context, note that you can also change the username and the password of the default user by using the second and third parameters.
var dbDynamic = new DynamicContext(serverName);

//Finally, you can set the correct table
var conn1 = dbDynamic.setDatabase('table1');

//If you want to connect to a different table
var conn2 = dbDynamic.setDatabase('table2');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM