【问题标题】:Entity Framework(Code First to an existing database) - overwrite a connection string in app.config at runtime实体框架(代码优先到现有数据库) - 在运行时覆盖 app.config 中的连接字符串
【发布时间】:2015-03-27 10:44:08
【问题描述】:

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

下面是 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?

【问题讨论】:

  • a) 您的用户帐户是否有权更改配置文件? (在 \Program Files\...)
  • b) 使用 XmlDoc 更改活动配置是自找麻烦...
  • a):是的,他有。 b):我想知道记忆的变化而不是身体的变化,你怎么看?

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


【解决方案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();

【讨论】:

  • Just-a-links 在这里不是一个好的答案。做一个总结或发表评论。
  • 这篇文章有点长,把整个东西都贴出来,你不觉得吗?即使是摘要也会错过重点。
  • @gigi,我使用的方法是不手动更改 app.config,而只是在构造函数中传递新的 connectionString。
【解决方案2】:

如果您的 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);
  }

}

【讨论】:

  • 嗨@ArhiChief,我已经尝试过这种方法,传递了一个手动构建的新connectionString,但是在存储库中例如,当我尝试执行context.Entity.ToList( ),我得到一个错误(没有创建数据库的权限),但我不想创建数据库,只需查询这个。
  • 可能,如果您使用 Code First,您的域模型和数据库模型不匹配,并且您的错误也比连接字符串中的数据库确实不存在。你有没有尝试做这样的事情:'var db = new NfceContext(conStr1); * 一些动作 *\ db = new NfceContext(conStr2);'?此外,请确保您的 DbContext 域模型对于您使用的所有数据库都是相同的。
  • 你说得对,我的域模型中缺少一些属性。型号不匹配。我会修改并给你答案
  • 就是这样!我忽略了在 app.config 中更改连接字符串的方法,并在构造函数中传递了连接字符串。此外,检查域模型和数据库模型是否匹配。谢谢。
  • 可能已经晚了,但是我想对模型匹配做一些补充。如果您将 Code First 与启用的迁移一起使用,请确保将迁移添加到要使用的所有数据库中。您需要这样做,因为 EF 模型创建过程从附加数据库的 dbo.__MigrationHistory 表中读取数据,并将其与上次迁移进行比较。 EF 使用它来确保自己的 DB 模型和它自己的域模型是相同的。但是有一些“墙黑客”可以关闭此步骤:您需要从项目中排除 Migrations 文件夹并重建您的项目。
猜你喜欢
  • 1970-01-01
  • 2013-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
  • 2011-10-31
  • 1970-01-01
相关资源
最近更新 更多