我想以编程方式设置连接字符串,绝对不会更改任何配置文件/注册表项。
我有这段代码,但不幸的是它引发了一个例外,“配置是只读的”。
ConfigurationManager.ConnectionStrings.Clear();
string connectionString = "Server=myserver;Port=8080;Database=my_db;...";
ConnectionStringSettings connectionStringSettings =
new ConnectionStringSettings("MyConnectionStringKey", connectionString);
ConfigurationManager.ConnectionStrings.Add(connectionStringSettings);
编辑:问题是我有现有的代码从配置中读取连接字符串。因此,手动或通过资源设置配置字符串似乎不是有效的选项。我真正需要的是一种以编程方式修改配置的方法。
我在post on my blog上写过这个。诀窍是使用反射来捅取值,以便访问非公共字段(和方法)。
例如。
var settings = ConfigurationManager.ConnectionStrings[ 0 ];
var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic );
fi.SetValue(settings, false);
settings.ConnectionString = "Data Source=Something";
我正在寻找关于允许用户通过选择本地SQL Server在单击一次应用程序中修改连接字符串的相同问题的答案。
下面的代码显示了一个用户表单,该表单与所有本地可用的SQL Server联系,并允许他们选择一个。然后,它为该服务器构造一个连接字符串,并从表单上的变量返回它。然后代码修改配置文件并保存它。
string NewConnection = "";
// get the user to supply connection details
frmSetSQLConnection frm = new frmSetSQLConnection();
frm.ShowDialog();
if (frm.DialogResult == DialogResult.OK)
{
// here we set the users connection string for the database
// Get the application configuration file.
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get the connection strings section.
ConnectionStringsSection csSection = config.ConnectionStrings;
foreach (ConnectionStringSettings connection3 in csSection.ConnectionStrings)
{
// Here we check for the preset string - this could be done by item no as well
if (connection3.ConnectionString == "Data Source=SQL204\\SQL2008;Initial Catalog=Transition;Integrated Security=True")
{
// amend the details and save
connection3.ConnectionString = frm.Connection;
NewConnection = frm.Connection;
break;
}
}
config.Save(ConfigurationSaveMode.Modified);
// reload the config file so the new values are available
ConfigurationManager.RefreshSection(csSection.SectionInformation.Name);
return clsDBMaintenance.UpdateDatabase(NewConnection))
}
解决这个问题的另一种方法是直接对集合进行操作:
var settings = ConfigurationManager.ConnectionStrings;
var element = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
var collection = typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
element.SetValue(settings, false);
collection.SetValue(settings, false);
settings.Add(new ConnectionStringSettings("ConnectionStringName", connectionString));
// Repeat above line as necessary
collection.SetValue(settings, true);
element.SetValue(settings, true);
我发现这对我有用:
Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
ConnectionStringsSection section = config.GetSection("connectionStrings") as ConnectionStringsSection;
if (section != null)
{
section.ConnectionStrings["MyConnectionString"].ConnectionString = connectionString;
config.Save();
}
这会覆盖现有的连接字符串。
我目前正在使用依赖注入来处理dev / prod与测试环境中的不同连接字符串。如果我想在dev和prod之间移动,我仍然需要手动更改webconfig,但是为了测试,我有一个IConnectionStringFactory接口,其默认实现查看Web配置和返回静态值的备用测试配置。这样,当我测试时,我只是将工厂设置为测试实现,它将返回我要求的密钥的测试连接字符串。否则它将在webconfig中查找。
我可以将它扩展到dev vs. prod的另一个实现,但是我在生产程序集中单独实现IConnectionStringFactory以及在我的测试程序集中测试实现时更加舒服。
您可以将其放在资源文件中。它不具有ConfigurationManager类的内置功能,但它可以工作。
假设Resources.resx:
Resources.Default.ConnectionString = "Server=myserver;" // etc
然后在你的代码中:
conn.ConnectionString = Resources.Default.ConnectionString
我知道,这是一个黑客攻击。
除了给出的其他答案,并假设连接字符串不仅仅是另一个配置变量或整体常量,您可以考虑使用SqlConnectionStringBuilder类而不是直接将字符串连接在一起。
编辑:Ups,对不起只是看到你基本上想要从其他来源读取你的连接字符串(我猜)。
看起来命名已更改为.net Core 2.1修改David Gardiner的答案这种方式适用于引用新旧版本:
var settings = ConfigurationManager.ConnectionStrings [0];
var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic );
if(fi == null)
{
fi = typeof(System.Configuration.ConfigurationElementCollection).GetField("_readOnly", BindingFlags.Instance | BindingFlags.NonPublic);
}
fi.SetValue(settings, false);
settings.ConnectionString = "Data Source=Something";
ConfigurationManager用于从配置文件中读取。
您的解决方案是简单地将conn.ConnectionString设置为您需要的conn字符串。