日期:2014-05-16  浏览次数:20518 次

为什么要检测数据库连接是否可用,项目经理说如果实现了这个功能,客户会认可你的软件很专业,很好用

如果用户很辛苦的输入了很多数据,点击保存时,才发现服务器连接不可用。这时用户肯定会很恼火,如果你是用户,你也会觉得很冤枉,辛苦输入的数据又不能保存,你干吗不早说呢,早点告诉我服务器不可用,我也可以不用白费功夫。

今天的文章就是为解决这个问题,如何检测SQL Server 服务是否可用,可以连接,以保证任何时候,用户输入数据的工作量不白费,节约客户的时间,如果发现SQL Server服务器不可用,要马上通知用户,阻止用户继续输入数据。做到软件是为解决问题,而不是增加麻烦。

我想到的第一个办法,是在保存数据的时候,检测服务器可否连接,这是必须的,代码如下

public static bool CheckConnectionAvailableBySql()
 {
         SqlConnection conn = new SqlConnection(ConnectionString);
          try
          {
               conn.Open();
               return true;
          }
          catch (Exception ex) { return false; }
}

?

?

但是,我们要达到的目标不是在保存数据时检测,而是用户打开程序后,随时要检测,于是我想到这样,再加一个Timer控件,在它的Tick事件中轮循检测数据库服务是否可用

private void timer_Tick(object sender, EventArgs e)
{
        bool available = Program.CheckConnectionAvailableBySql();
        if (available)
        {               
            Console.WriteLine("server is available");
        }          

}

再把这个封装成BaseForm窗体基类,各种的业务单据输入窗体都继承于这个窗体,这样就实现了在用户打开窗体,输入数据时,随时可以检测数据库连接是否可用。

如果你觉得用SqlConnection会造成对SQL Server服务的性能有影响,可以考虑用网络Ping命令,再配合ServiceProcess对象模型,以提高性能。请看下面的实现代码

private static bool CheckConnectionAvailableByNetwork()
{
     bool available = false;
     SqlConnectionStringBuilder conection = new SqlConnectionStringBuilder(ConnectionString);
     string machineName = conection.DataSource;
     Ping ping = new Ping();
     PingReply reply = ping.Send(machineName, 4000);
     if (reply.Status == IPStatus.Success)
     {
         ServiceController[] AvailableServices = ServiceController.GetServices(machineName);
         foreach (ServiceController AvailableService in AvailableServices)
         {
            if (AvailableService.ServiceName.Equals("MSSQLSERVER", StringComparison.InvariantCultureIgnoreCase))
              {
                  if (AvailableService.Status == ServiceControllerStatus.Running)
                  {
                       available = true;
                       break;
                  }
               }
          }
     }
     return available;
}

这个方法是检测指定的机器的SQL Server服务是否可用,那一句foeach循环遍历改成Linq效率会更好一些。

?

留言的园友提供了另一个实现思路,用网络连接方式,判断SQL Server是否可用,再把它发送到应用程序中。这个思路在我的ERP Solution已经实现了,现在把它分享出来,供大家参考。

image

为实现这个功能,分两个模块,Check SQL Server Available是服务器检测程序,检测SQL Servver是否可用。把它单独放到一个进程中,Main Form是应用程序,把它理解为客户端程序,用于输入数据,保存到SQL Server中。把检测SQL Server服务器是否可用放到一个单独的进程中,是为了节省Main Form程序的资源,我认为用Timer来轮循SQL Server是否可用,会消耗一些内存和CPU,独立出来,Main Form的性能会好一些。

上面给出的代码,CheckConnectionAvailableBySql/CheckConnectionAvailableByNetwork和timer_Tick,就是Check SQL Server Available的代码,下面来分析它如何把SQL Server服务器是否可用的信息发送到Main Form应用程序。

这里使用的是Socket通信,Check SQL Server Available检测SQL Servver是否可用,如果可用,发送S字母到Main Form中,不可用则发送F字母到Main Form中,Main Form根据收到的消息做出处理。如果收到F消息,表