Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make SqlConnection timeout more quickly

I am using an SQL connection string with SqlClient.SqlConnection and specifying Connection Timeout=5 in the string, but it still waits 30 seconds before returning failure. How do I make it give up and return faster? I'm on a fast local network and don't want to wait 30 seconds. The servers that are not turned on take 30 seconds to fail. This is just a quick utility program that's going to always run just on this local network.

Edit: Sorry if I was unclear. I want the SqlConnection.Open to fail more quickly. Hopefully that could be deduced from the fact that the servers I want to fail more quickly are turned off.

Edit: It seems that the setting only fails sometimes. Like it knows the IP address of the server, and is using TCP/IP to talk to it (not local) but can't contact SQL Server at that address? I'm not sure what the pattern is, but I don't see the problem when connecting locally with SQL Server stopped, and I don't see it when attempting to connect to a non-existent server. I have seen it when attempting to contact a server where the Windows 2008 firewall is blocking SQL Server, though.

like image 912
BlueMonkMN Avatar asked Sep 01 '10 14:09

BlueMonkMN


People also ask

How do I change timeout in SqlConnection?

You can set the amount of time a connection waits to time out by using the Connect Timeout or Connection Timeout keywords in the connection string. A value of 0 indicates no limit, and should be avoided in a ConnectionString because an attempt to connect waits indefinitely.

What is the default connection timeout for SqlConnection?

The time (in seconds) to wait for a connection to open. The default value is 15 seconds.

Does using automatically close SqlConnection?

Answers. Yes. When the using block ends, the connection automatically closes (That is what IDisposable is for). So, do not close the connection explicitly.

What happens if SqlConnection is not closed?

If you open the connection and don't close it, then it would decrease the connection pools and limits available for connecting to database again. It is always recommended to close the connection and data reader objects explicitly when you use them.


1 Answers

It looks like all the cases that were causing long delays could be resolved much more quickly by attempting a direct socket connection like this:

foreach (string svrName in args)
{
   try
   {
      System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient(svrName, 1433);
      if (tcp.Connected)
         Console.WriteLine("Opened connection to {0}", svrName);
      else
         Console.WriteLine("{0} not connected", svrName);
      tcp.Close();
   }
   catch (Exception ex)
   {
      Console.WriteLine("Error connecting to {0}: {1}", svrName, ex.Message);
   }
}

I'm going to use this code to check if the server responds on the SQL Server port, and only attempt to open a connection if it does. I thought (based on others' experience) that there would be a 30 second delay even at this level, but I get a message that the machine "actively refused the connection" on these right away.

Edit: And if the machine doesn't exist, it tells me that right away too. No 30-second delays that I can find.

Edit: Machines that were on the network but are not turned off still take 30 seconds to fail I guess. The firewalled machines fail faster, though.

Edit: Here's the updated code. I feel like it's cleaner to close a socket than abort a thread:

static void TestConn(string server)
{
   try
   {
      using (System.Net.Sockets.TcpClient tcpSocket = new System.Net.Sockets.TcpClient())
      {
         IAsyncResult async = tcpSocket.BeginConnect(server, 1433, ConnectCallback, null);
         DateTime startTime = DateTime.Now;
         do
         {
            System.Threading.Thread.Sleep(500);
            if (async.IsCompleted) break;
         } while (DateTime.Now.Subtract(startTime).TotalSeconds < 5);
         if (async.IsCompleted)
         {
            tcpSocket.EndConnect(async);
            Console.WriteLine("Connection succeeded");
         }
         tcpSocket.Close();
         if (!async.IsCompleted)
         {
            Console.WriteLine("Server did not respond");
            return;
         }
      }
   }
   catch(System.Net.Sockets.SocketException ex)
   {
      Console.WriteLine(ex.Message);
   }
}
like image 157
BlueMonkMN Avatar answered Sep 29 '22 11:09

BlueMonkMN