运行时修改App.config文件----完善登录时的用户体验与对XmlDocument对象进行操作札记

  代号为 X 的(C/S)应用程序是给我们内部同事使用,以配置数据库的各表值、参数。当X程序起动后,每个人都期望连接自己电脑的本地数据库(Sql 2005),而往往待我将X程序发布后,配置文件信息总是默认成我的开发机器中的配置信息,从而导致他们登录时失败,为此他们需手动修改配置文件(App.config),让人感觉其用户体验真是相当的不爽。
  于是我想在启动应用程序之前,对数据库连接进行试探性检验,如果连接失败则立即返回,可不能像默认时长达15秒的等待时间,显然这种假死状态的用户体验同样是令人相当沮丧的,何况 X 程序还是给程序员用的。

  先看看试探性检验数据库连接代码(代码分页在两个物理层):

  1.在静态公共类(为数据访问层提供服务) 【namespace DotNet.DBUtility】

View Code
     /// <summary>
/// 判断是否能连接上默认的数据库,基于配置文件
/// </summary>
/// <returns></returns>
public static bool CheckConnectToSql()
{
connectionString
= String.Format("{0}{1};", connectionString, "connect timeout = 1");
using (SqlConnection connection = new SqlConnection(connectionString))
{
if (connection != null)
{
try
{
              //连接失败后由异常控制程序流程(虽然这不是一个好的做法)
connection.Open();
return true;
}
catch (InvalidOperationException invalidEx)
{
return false;
}
catch (SqlException sqlEx)
{
return false;
}

}
else
{
return false;
}
}
}

  2.数据访问层 【namespace MonsoftConfig.SQLServerDAL】

View Code
     /// <summary>
/// 判断是否能连接上默认的数据库,基于配置文件
/// </summary>
/// <returns>bool</returns>
public bool IsConectedDB()
{
if (DbHelperSQL.CheckConnectToSql())
{
return true;
}
else
{
return false;
}
}

   但凡与数据库直接打交道的逻辑都放在 DotNet.DBUtility层,它为数据库访问层(Dal)的调用提供服务:即在Dal层可以看见操作数据库的基本方法Add、Update、Delete、Select(包括分页)等,而真正的ExecuteNonQuery()、ExecuteScalar()、DataAdapter的Fill()皆在DotNet.DBUtility层。

  在试图连接数据库前,最需要注意的是对连接字符串要添加connect timeout = 1,保证在连接数据库失败后能即时返回(不能设置为0),否则为默认的15秒后返回(这个等待令人相当地崩溃)。

如果连接成功了,那么该去哪就去哪(一般是登录界面);而连接失败后,我会提供用户对连接字符串进行重置的功能界面:

数据库访问设置

保存时,会收集界面的文本信息,并再一次试探性的访问数据库。如果连接不成功,则提示不能连接;直至连接成功后才离开该页面,去往登录界面。

View Code
        string serverName = StringPlus.SqlInjection(txtServerName.Text);
string dataBaseName = StringPlus.SqlInjection(txtDataBaseName.Text);
string loginName = StringPlus.SqlInjection(txtLoginName.Text);
string loginPWD = StringPlus.SqlInjection(txtLoginPWD.Text);

string connStrValue = String.Format("Data Source={0};DataBase={1};User ID={2};Password={3};", serverName, dataBaseName, loginName, loginPWD);

//连接成功
if (userDal.IsConectedDB(connStrValue + "connect timeout = 1"))
{
ConfigHelper.SetAppSettings(Application.ExecutablePath
+ ".config", "MonsoftConfigConnectionString", connStrValue);
IsLoginSucc
= true;
this.Close();
}
else
{
lblErrorConnectDB.Visible
= true;
SaveSuccessTimer.Enabled
= true;//对提示的呈现时间进行计时
}

 

View Code
     /// <summary>
/// 修改或保存配置信息
/// </summary>
/// <param name="AppKey">属性 key 的值</param>
/// <param name="AppValue">属性 value 的值</param>
public static void SetAppSettings(string configPath, string AppKey, string AppValue)
{
XmlNode nodeAppSetting;
XmlElement eleTempAdd;
XmlDocument eleDocumnet
= new XmlDocument();
eleDocumnet.Load(configPath);

nodeAppSetting
= eleDocumnet.SelectSingleNode("//appSettings");
eleTempAdd
= (XmlElement)nodeAppSetting.SelectSingleNode("//add[@key='" + AppKey + "']");

if (eleTempAdd != null)
{
eleTempAdd.SetAttribute(
"value", AppValue);
}
else
{
eleTempAdd
= eleDocumnet.CreateElement("add");
eleTempAdd.SetAttribute(
"key", AppKey);
eleTempAdd.SetAttribute(
"value", AppValue);
nodeAppSetting.AppendChild(eleTempAdd);
}
eleDocumnet.Save(configPath);
}

   记录这个札记的初衷是想对XmlDocument的相关操作进行一个总结,却不想引出上述那么多细节。不难想像,软件中的一个小功能(或者是不被重视的用户体验问题),想要完好的实现出来,着实是不容易的(期间的思路过程可见一斑)。

 

posted @ 2011-09-05 10:24  罗霄(Sto)  阅读(281)  评论(0编辑  收藏  举报