在做一些数据库应用程序的时候经常遇到动态配置数据库,所以写了一个小程序,利用App.Config动态读写数据库连接字符串,那些还在用Adapter控件的同志们赶紧抛弃吧。
主要实现代码:
//----------------------------------------------------
public class ConfigureAppConfig
{
//静态构造,不能实例化
static ConfigureAppConfig() { }
/**//// <summary>
/// 获取AppSettings配置节中的Key值
/// </summary>
/// <param name="keyName">Key's name</param>
/// <returns>Key's value</returns>
public static string GetAppSettingsKeyValue(string keyName)
{
return ConfigurationManager.AppSettings.Get(keyName);
}
/**//// <summary>
/// 获取ConnectionStrings配置节中的值
/// </summary>
/// <returns></returns>
public static string GetConnectionStringsElementValue()
{
ConnectionStringSettings settings = System.Configuration.ConfigurationManager.ConnectionStrings["connectionString"];
return settings.ConnectionString;
}
/**//// <summary>
/// 保存节点中ConnectionStrings的子节点配置项的值
/// </summary>
/// <param name="elementValue"></param>
public static void ConnectionStringsSave(string ConnectionStringsName, string elementValue)
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.ConnectionStrings.ConnectionStrings["connectionString"].ConnectionString = elementValue;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
}
/**//// <summary>
/// 判断appSettings中是否有此项
/// </summary>
private static bool AppSettingsKeyExists(string strKey, Configuration config)
{
foreach (string str in config.AppSettings.Settings.AllKeys)
{
if (str == strKey)
{
return true;
}
}
return false;
}
/**//// <summary>
/// 保存appSettings中某key的value值
/// </summary>
/// <param name="strKey">key's name</param>
/// <param name="newValue">value</param>
public static void AppSettingsSave(string strKey, string newValue)
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (AppSettingsKeyExists(strKey, config))
{
config.AppSettings.Settings[strKey].Value = newValue;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
}
}
如果你的程序是对其它程序的配置文件进行操作,代码如下:
ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
filemap.ExeConfigFilename = filePath;//配置文件路径
config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
if (AppSettingsKeyExists("Refresh", config))
{
config.AppSettings.Settings["Refresh"].Value = M_TimeRead.ToString();
}
if (AppSettingsKeyExists("MachineNo", config))
{
config.AppSettings.Settings["MachineNo"].Value = M_MachineNo;
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
config.ConnectionStrings.ConnectionStrings["connectionString"].ConnectionString = M_ConnectionString;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
数据库字符串加密
ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
filemap.ExeConfigFilename = Application.ExecutablePath + ".Config"; //filePath;
config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
//指定我所要的节点
ConfigurationSection section = config.ConnectionStrings;
if ((section.SectionInformation.IsProtected == false) && (section.ElementInformation.IsLocked == false))
{
//制定节点加密
section.SectionInformation.ProtectSection(protect);
//即使没有修改也保存设置
section.SectionInformation.ForceSave = true;
//配置文件内容保存到xml
config.Save(ConfigurationSaveMode.Full);
}
//----------------------------------------------------
扩展Configuration的功能
获取连接字符串
View Code
///<summary>依据连接串名字connectionName返回数据连接字符串 </summary>
///<param name="connectionName">连接串的</param>
///<param name="config"></param>
///<returns></returns>
public static string GetConnectionStringsConfig(this Configuration config, string connectionName)
{
string connectionString = config.ConnectionStrings.ConnectionStrings[connectionName].ConnectionString;
////Console.WriteLine(connectionString);
return connectionString;
}
复制代码
更新连接字符串
View Code
///<summary>
///更新连接字符串
///</summary>
///<param name="newName">连接字符串名称</param>
///<param name="newConString">连接字符串内容</param>
///<param name="newProviderName">数据提供程序名称</param>
///<param name="config">Configuration实例</param>
public static void UpdateConnectionStringsConfig(this Configuration config, string newName, string newConString, string newProviderName)
{
bool isModified = false;
//记录该连接串是否已经存在
//如果要更改的连接串已经存在
if (config.ConnectionStrings.ConnectionStrings[newName] != null)
{ isModified = true; }
//新建一个连接字符串实例
ConnectionStringSettings mySettings = new ConnectionStringSettings(newName, newConString, newProviderName);
// 如果连接串已存在,首先删除它
if (isModified)
{
config.ConnectionStrings.ConnectionStrings.Remove(newName);
}
// 将新的连接串添加到配置文件中.
config.ConnectionStrings.ConnectionStrings.Add(mySettings);
// 保存对配置文件所作的更改
config.Save(ConfigurationSaveMode.Modified);
}
复制代码
获取appSettings配置节的value项
View Code
///<summary>
///返回config文件中appSettings配置节的value项
///</summary>
///<param name="strKey"></param>
///<param name="config">Configuration实例</param>
///<returns></returns>
public static string GetAppSettingsItemValue(this Configuration config, string strKey)
{
foreach (KeyValueConfigurationElement key in config.AppSettings.Settings)
{
if (key.Key == strKey)
{
return config.AppSettings.Settings[strKey].Value;
}
}
return string.Empty;
}
复制代码
获取所有的appSettings的节点
View Code
/// <summary>
/// 获取所有的appSettings的节点。
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public static Dictionary<string,string> GetAppSettings(this Configuration config)
{
Dictionary<string,string> dict = new Dictionary<string,string>();
foreach (KeyValueConfigurationElement key in config.AppSettings.Settings)
{
dict[key.Key] = key.Value;
}
return dict;
}
复制代码
更新或增加appSettings配置节增加一对键、值对。
View Code
///<summary>
///更新在config文件中appSettings配置节增加一对键、值对。
///</summary>
///<param name="newKey"></param>
///<param name="newValue"></param>
///<param name="config"></param>
public static void UpdateAppSettingsItemValue(this Configuration config, string newKey, string newValue)
{
UpdateAppSettingsItemNoSave(config, newKey, newValue);
////// Save the changes in App.config file.
config.Save(ConfigurationSaveMode.Modified);
////// Force a reload of a changed section.
////ConfigurationManager.RefreshSection("appSettings");
}
复制代码
删除 appSettings的一个或多个节点
/// <summary>
/// 删除 appSettings的一个节点。
/// </summary>
/// <param name="config"></param>
/// <param name="key"></param>
public static void RemoveAppSettingsItemValue(this Configuration config, string key)
{
config.AppSettings.Settings.Remove(key);
config.Save(ConfigurationSaveMode.Modified);
}
/// <summary>
/// 删除 appSettings的多个节点
/// </summary>
/// <param name="config"></param>
/// <param name="keys"></param>
public static void RemoveAppSettingsItems(this Configuration config, string[] keys)
{
foreach(string key in keys)
config.AppSettings.Settings.Remove(key);
config.Save(ConfigurationSaveMode.Modified);
}
复制代码
增加或appSettings配置节增加多对键、值对
/// <summary>
///更新在config文件中appSettings配置节增加多对键、值对。
/// </summary>
/// <param name="config"></param>
/// <param name="items"></param>
public static void UpdateAppSettings(this Configuration config, Dictionary<string, string> items)
{
foreach (string key in items.Keys)
{
UpdateAppSettingsItemNoSave(config, key, items[key]);
}
config.Save(ConfigurationSaveMode.Modified);
}
private static void UpdateAppSettingsItemNoSave(Configuration config, string newKey, string newValue)
{
bool isModified = false;
foreach (KeyValueConfigurationElement key in config.AppSettings.Settings)
{
if (key.Key == newKey)
{ isModified = true; }
}
// You need to remove the old settings object before you can replace it
if (isModified)
{ config.AppSettings.Settings.Remove(newKey); }
// Add an Application Setting.
config.AppSettings.Settings.Add(newKey, newValue);
}
复制代码
以上是对connectionStrings 和 appSetting配置节的一些操作,较多的参考网上资源。
对于DictionarySectionHandler 、NameValueFileSectionHandler 、SingleTagSectionHandler的实现真的不是很多操作,但还是实现了DictionarySectionHandler 、NameValueFileSectionHandler ,至于SingleTagSectionHandler有待进一步实现,或有哪位仁兄实现了,可以回复,谢谢!
通用获取key-value 键值对Section值的集合
/// <summary>
/// 通用获取key-value 键值对Section值的集合,可用于DictionarySectionHandler或NameValueSectionHandler 定义的配置节 NameValueSectionHandler的Key值不能重复
/// </summary>
/// <param name="sectionName"></param>
/// <param name="config"></param>
/// <returns>没有配置节时返回null</returns>
public static Dictionary<string, string> GetKeyValueSectionValues(this Configuration config, string sectionName)
{
////KeyValueConfigurationSection appSettings = (KeyValueConfigurationSection)config.GetSection(sectionName);
var section = config.GetSection(sectionName);
if (section == null)
return null;
Dictionary<string, string> result = new Dictionary<string, string>();
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(section.SectionInformation.GetRawXml());
System.Xml.XmlNode xnode = xdoc.ChildNodes[0];
IDictionary dict = (IDictionary)(new DictionarySectionHandler().Create(null, null, xnode));
foreach (string str in dict.Keys)
{
result[str] = (string)dict[str];
}
return result;
}
复制代码
由于Framework框架没有提供DictionarySection的节点类,不能直接解释出节点中的元素,因些只能使用XML,通过IConfigurationSectionHandler.Create接口,即DictionarySectionHandler().Create方法,实现了元素的集合。
获取子节点为key-value 键值对的值
/// <summary>
/// 获取子节点为key-value 键值对的值,可用于DictionarySectionHandler或NameValueSectionHandler 定义的配置节
///
/// </summary>
/// <param name="sectionName">定点名称</param>
/// <param name="key">key 的值,不存在的Key值将返回空</param>
/// <param name="config">打开的配置文件。</param>
/// <returns></returns>
public static string GetKeyValueSectionItemValue(this Configuration config, string sectionName, string key)
{
var section = config.GetSection(sectionName).SectionInformation;
if (section == null)
return null;
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(section.GetRawXml());
System.Xml.XmlNode xnode = xdoc.ChildNodes[0];
IDictionary dict = (IDictionary)(new DictionarySectionHandler().Create(null, null, xnode));
if (dict.Contains(key))
return (string)dict[key];
else
return null;
}
复制代码
更新配置节,相同的就修改,没有的就增加。
/// <summary>
/// 更新配置节,相同的就修改,没有的就增加。
/// </summary>
/// <param name="config"></param>
/// <param name="sectionName"></param>
/// <param name="items"></param>
public static void UpdateKeyValueSectionValues(this Configuration config, string sectionName, Dictionary<string, string> items)
{
Dictionary<string, string> orgItem = GetKeyValueSectionValues(config, sectionName);
if (orgItem == null)
orgItem = new Dictionary<string, string>();
foreach (string key in items.Keys)
{
orgItem[key] = items[key];
}
UpdateKeyValueSection(config, sectionName, orgItem);
}
private static void UpdateKeyValueSection(Configuration config, string sectionName, Dictionary<string, string> items)
{
config.Sections.Remove(sectionName);
AppSettingsSection section = new AppSettingsSection();
config.Sections.Add(sectionName, section);
foreach (string key in items.Keys)
{
section.Settings.Add(new KeyValueConfigurationElement(key, items[key]));
}
section.SectionInformation.Type = typeof(DictionarySectionHandler).AssemblyQualifiedName;
config.Save(ConfigurationSaveMode.Modified);
}
复制代码
更新配置节在这里使用欺骗的做法,我们使用一个AppSettingsSection 配置节类,把Dictionary的键值对作为KeyValueConfigurationElement元素加入到AppSettingsSection 的Settings集合里,在序列化到Config文件前,把section.SectionInformation.Type 更改为typeof(DictionarySectionHandler).AssemblyQualifiedName的字符串,保存后,我们就可以得到一个DictionarySectionHandler的配置节了,些方法很好地解决了序列化的问题。
删除配置点的一些配置。
/// <summary>
/// 删除配置点的一些配置。
/// </summary>
/// <param name="config"></param>
/// <param name="sectionName"></param>
/// <param name="items"></param>
public static void RemoveKeyValueSectionValues(this Configuration config, string sectionName, Dictionary<string, string> items)
{
Dictionary<string, string> orgItem = GetKeyValueSectionValues(config, sectionName);
if (orgItem != null)
{
foreach (string key in items.Keys)
{
orgItem.Remove(key);
}
UpdateKeyValueSection(config, sectionName, orgItem);
}
}
复制代码
/// <summary>
/// 删除配置节。
/// </summary>
/// <param name="config"></param>
/// <param name="sectionName"></param>
public static void RemoveSection(this Configuration config, string sectionName)
{
config.Sections.Remove(sectionName);
config.Save(ConfigurationSaveMode.Modified);
}
复制代码
以上的方法全部完成了配置节的增删改,对于配置节组,由于较少使用,暂时不想去完善了,而且一个组其实可以看作是多个单独配置节的组合,意义不大。