实体框架(代码优先于现有数据库) - 在运行时覆盖app.config中的连接字符串

时间:2015-01-28 13:47:07

标签: c# sql-server winforms entity-framework

我需要动态地将我的应用程序(Windows窗体)连接到SQL Server数据库,并且我的app.config中有3个连接字符串(其中1个我想动态更改)。

Bellow是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>

在我的DbContext中,我有这个:

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

}

我尝试使用 AppDomain.CurrentDomain.SetupInformation.ConfigurationFile 在类中更改此connectionString的方法。如果我检查在调试模式下运行,app.vshost.exe.config上的connectionStrings会被更改,但是app.config没有(我想应该修改app.config)。

当我尝试做一个例子:context.MyEntity.ToList()时,它给我一个像这样的错误“你没有权限创建表...”如果我检查连接字符串在这个时候,它是旧的(在我修改之前)。

下面的代码可以显示我所说的内容:

覆盖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);    
}

控制器的构造函数:

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

那么,我做错了什么?我是否需要更改app.config而不是vhost.config?

2 个答案:

答案 0 :(得分:1)

我首先在运行时为数据库设置连接字符串this article。看看这个;即使在你的情况下也可能有用。

简而言之,您可以创建一个分部类来访问DbContext构造函数重载,该重载将连接字符串作为参数(例如,来自我的文章):

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

    }
}

然后你可以使用EntityConnectionStringBuilder来构建和传递连接字符串(例子也来自我的文章):

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

答案 1 :(得分:1)

如果你的NfceContext不是静态对象,你可以创建另一个构造函数,它将连接字符串名称作为参数,如下所示:

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

否则,如果您的上下文是静态对象,我认为什么是不好的做法,您可以编写公共方法,在NfceContext中创建新的DbContext实例:

public class NfceContext : DbContext{
  static NfceContext context;

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

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

}