简体   繁体   中英

Entity Framework(Code First to an existing database) - overwrite a connection string in app.config at runtime

I need to connect my app(windows forms) to a SQL Server Database dynamically and i have in my app.config, 3 connection strings(where 1 of them i want to change dynamically).

Bellow is the app.config:

  <connectionStrings>
    <add name="NfceConnPortalInterno"
         providerName="System.Data.SqlClient"
         connectionString="Data Source=lab;Initial Catalog=portal;Persist Security Info=True;User ID=micportal;Password=150302;language=us_english"/>

    <add name="NfceConnPortalExterno"
             providerName="System.Data.SqlClient"
             connectionString="Data Source=10.10.0.1,8081;Initial Catalog=portal;Persist Security Info=True;User ID=micportal;Password=\\-W?98xpT;language=us_english"/>


    <!-- this one will be modified in runtime. -->
    <add
      name="NfceContext"
      connectionString="data source=(localdb)\v11.0;initial catalog=Blogging;Connection Timeout=320;Persist Security Info=True;integrated security=True;language=us_english;MultipleActiveResultSets=True;App=EntityFramework"
      providerName="System.Data.SqlClient" />    

  </connectionStrings>

In my DbContext i have this:

public NfceContext() : base("name=NfceContext")
{

}

Im trying an approach of changing this connectionString in a class, using AppDomain.CurrentDomain.SetupInformation.ConfigurationFile . If i check running on debug mode, the connectionStrings on the app.vshost.exe.config is changed, but the app.config not(I guess that the app.config should be modified).

When i try to do for an example: context.MyEntity.ToList(), it´s gives me an error like this"you don´t have permission to create table..." and if i check the connection string at this time, it´s the old one(before i modify).

The code bellow can show what i said:

Method to overwrite the connection string in the app.config:

private void ModifyNfceContext(string dataSource, string portal, string senha)
{    
    XmlDocument xml = new XmlDocument();
    xml.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

    XmlNodeList lista = xml.DocumentElement.SelectNodes(String.Format("connectionStrings/add [@name='{0}']", "NfceContext")); 
    XmlNode node = lista[0];

    string connectionString = node.Attributes["connectionString"].Value;
    SqlConnectionStringBuilder connStringBuilder = new SqlConnectionStringBuilder(connectionString);
    connStringBuilder.InitialCatalog = portal;
    connStringBuilder.DataSource = dataSource;
    connStringBuilder.IntegratedSecurity = true;
    connStringBuilder.UserID = "mic" + portal;
    connStringBuilder.Password = senha;

    node.Attributes["connectionString"].Value = connStringBuilder.ConnectionString;
    xml.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);    
}

The controller´s contructor:

public NfceController()
        {
            if (this.context == null)
            {
                ModifyNfceContext(this.dataSource, this.portal, this.senha);
                //At this moment, the connectionString should be modified.
                this.context = new NfceContext();       
            }   

            this.repositoryNfce = new RepositoryNfce(context);
        }

So, what am i doing wrong? Do i need to change the app.config instead of vhost.config?

I had written this article on setting connection strings at runtime for database first. Check it out; it might be useful even in your case.

In short, you can create a partial class to get access to a DbContext constructor overload that takes a connection string as a parameter (example from my article):

public partial class peopleEntities : DbContext
{
    public peopleEntities(String connectionString)
        : base(connectionString)
    {

    }
}

And then you can use EntityConnectionStringBuilder to build and pass the connection string (example also from my article):

            EntityConnectionStringBuilder csb = new EntityConnectionStringBuilder();
            csb.Metadata = "res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl";
            csb.Provider = "System.Data.SqlServerCe.4.0";
            csb.ProviderConnectionString = "data source=people.sdf";
            String entityConnStr = csb.ToString();

If your NfceContext is not static object, you can create another constructor what will take a connection string name as the parametr, something like this:

public class NfceContext : DbContext{
   public NfceContext (string appConfigConStrName) : base (appConfigConStrName) { }
}

Otherwise, if your context is static object, what is bad practice as I think, you can write public method what will create new instance of DbContext inside your NfceContext:

public class NfceContext : DbContext{
  static NfceContext context;

  public static NfceContext() {
     context = new NfceContext();
  }

  public void ChangeDB(string appConfigConStr) {
      context = new NfceContext(appConfigConStr);
  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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