2010-09-01 42 views
14

Tôi đang sử dụng chuỗi kết nối SQL với SqlClient.SqlConnection và chỉ định Thời gian chờ kết nối = 5 trong chuỗi nhưng vẫn chờ 30 giây trước khi trả về lỗi. Làm cách nào để từ bỏ và trả lại nhanh hơn? Tôi đang ở trên mạng nội bộ nhanh và không muốn đợi 30 giây. Các máy chủ không được bật mất 30 giây để không thành công. Đây chỉ là một chương trình tiện ích nhanh chóng sẽ luôn chạy trên mạng cục bộ này.Làm thế nào để làm cho thời gian chờ SqlConnection nhanh hơn

Chỉnh sửa: Xin lỗi nếu tôi không rõ. Tôi muốn SqlConnection.Open thất bại nhanh hơn. Hy vọng rằng có thể được suy ra từ thực tế là các máy chủ tôi muốn thất bại nhanh hơn được tắt.

Chỉnh sửa: Dường như cài đặt chỉ thỉnh thoảng không thành công. Giống như nó biết địa chỉ IP của máy chủ, và đang sử dụng TCP/IP để nói chuyện với nó (không phải địa phương) nhưng không thể liên lạc với SQL Server tại địa chỉ đó? Tôi không chắc chắn những gì các mô hình được, nhưng tôi không thấy vấn đề khi kết nối cục bộ với SQL Server dừng lại, và tôi không nhìn thấy nó khi cố gắng kết nối với một máy chủ không tồn tại. Tôi đã nhìn thấy nó khi cố gắng liên lạc với một máy chủ mà tường lửa Windows 2008 đang chặn máy chủ SQL, mặc dù.

Trả lời

10

Dường như tất cả các trường hợp đó đã gây ra sự chậm trễ dài có thể được giải quyết nhiều nhanh hơn bằng cách cố gắng kết nối ổ cắm trực tiếp như thế này:

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); 
    } 
} 

Tôi sẽ sử dụng mã này để kiểm tra xem máy chủ phản hồi trên cổng SQL Server và chỉ cố mở kết nối nếu có.Tôi nghĩ (dựa trên kinh nghiệm của người khác) rằng sẽ có một sự chậm trễ 30 giây ngay cả ở cấp độ này, nhưng tôi nhận được một thông báo rằng máy "tích cực từ chối kết nối" trên những ngay lập tức.

Chỉnh sửa: Và nếu máy không tồn tại, nó cũng cho tôi biết rằng ngay lập tức. Không có sự chậm trễ 30 giây mà tôi có thể tìm thấy.

Chỉnh sửa: Máy đã ở trên mạng nhưng không tắt vẫn mất 30 giây để không thành công. Tuy nhiên, các máy tường lửa không hoạt động nhanh hơn.

Chỉnh sửa: Đây là mã được cập nhật. Tôi cảm thấy như nó sạch hơn để đóng một ổ cắm hơn hủy bỏ một sợi:

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); 
    } 
} 
3

Cập nhật 2 Tôi khuyên bạn nên hết thời gian chờ của riêng mình. Một cái gì đó như thế này:

internal static class Program 
{ 
    private static void Main(string[] args) 
    { 
     Console.WriteLine(SqlServerIsRunning("Server=foobar; Database=tempdb; Integrated Security=true", 5)); 
     Console.WriteLine(SqlServerIsRunning("Server=localhost; Database=tempdb; Integrated Security=true", 5)); 
    } 

    private static bool SqlServerIsRunning(string baseConnectionString, int timeoutInSeconds) 
    { 
     bool result; 

     using (SqlConnection sqlConnection = new SqlConnection(baseConnectionString + ";Connection Timeout=" + timeoutInSeconds)) 
     { 
      Thread thread = new Thread(TryOpen); 
      ManualResetEvent manualResetEvent = new ManualResetEvent(false); 
      thread.Start(new Tuple<SqlConnection, ManualResetEvent>(sqlConnection, manualResetEvent)); 
      result = manualResetEvent.WaitOne(timeoutInSeconds*1000); 

      if (!result) 
      { 
       thread.Abort(); 
      } 

      sqlConnection.Close(); 
     } 

     return result; 
    } 

    private static void TryOpen(object input) 
    { 
     Tuple<SqlConnection, ManualResetEvent> parameters = (Tuple<SqlConnection, ManualResetEvent>)input; 

     try 
     { 
      parameters.Item1.Open(); 
      parameters.Item1.Close(); 
      parameters.Item2.Set(); 
     } 
     catch 
     { 
      // Eat any exception, we're not interested in it 
     } 
    } 
} 

Cập nhật 1

Tôi vừa thử nghiệm này trên máy tính của riêng tôi sử dụng mã này:

internal static class Program 
{ 
    private static void Main(string[] args) 
    { 
     SqlConnection con = new SqlConnection("Server=localhost; Database=tempdb; Integrated Security=true;Connection Timeout=5"); 
     Console.WriteLine("Attempting to open connection with {0} second timeout, starting at {1}.", con.ConnectionTimeout, DateTime.Now.ToLongTimeString()); 

     try 
     { 
      con.Open(); 
      Console.WriteLine("Successfully opened connection at {0}.", DateTime.Now.ToLongTimeString()); 
     } 
     catch (SqlException) 
     { 
      Console.WriteLine("SqlException raised at {0}.", DateTime.Now.ToLongTimeString()); 
     } 
    } 
} 

và nó tuân theo các giá trị Connection Timeout trong chuỗi kết nối . Điều này là với .NET 4 so với SQL Server 2008 R2. Phải thừa nhận rằng, đó là một kết nối localhost mà có thể cho kết quả khác nhau nhưng nó có nghĩa là tôi không thể tái tạo vấn đề.

Tôi chỉ có thể đề xuất thử một đoạn mã tương tự trong môi trường mạng của bạn và xem liệu bạn có tiếp tục thấy thời gian chờ lâu hay không.

Câu trả lời cũ (không chính xác) Tôi đã nghĩ không chính xác thuộc tính ConnectionTimeout đã được đặt, nhưng không phải.

Thử đặt SqlConnection.ConnectionTimeout thay vì sử dụng chuỗi kết nối.

+0

ConnectionTimeout là một tài sản chỉ đọc – BlueMonkMN

+0

Tôi đang đánh một mẫu rất kỳ lạ ở đây. Thời gian chờ dường như hoạt động khi tôi kết nối với hệ thống cục bộ của mình với SQL Server đã dừng. Dường như nó hoạt động khi tôi cố gắng kết nối với một máy chủ không tồn tại. Nhưng nó dường như không hoạt động khi tôi cố gắng kết nối với một máy chủ tồn tại, nhưng có tường lửa chặn SQL và/hoặc không có SQL Server được cài đặt. – BlueMonkMN

+0

Một chủ đề thú vị về vấn đề này ở đây: http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.adonet/topic48533.aspx. Tôi khuyên bạn nên triển khai cơ chế thời gian chờ của riêng mình - quay vòng một chuỗi để thử mở và giết nó nếu nó không thành công trong khoảng thời gian chờ bạn muốn. –

0

Thời gian chờ của lệnh và Thời gian chờ kết nối là hai điều khác nhau.

SqlConnection.ConnectionTimeout là "thời gian (tính bằng giây) chờ kết nối mở. Giá trị mặc định là 15 giây". Thats chỉ được sử dụng khi bạn gọi SqlConnection.Open().

SqlCommand.CommandTimeout thực hiện những gì bạn muốn làm.

+0

Không, không. Tôi muốn mở để thời gian chờ, không phải là một lệnh. – BlueMonkMN

+0

SqlConnection.ConnectionTimeout là những gì bạn muốn – jrummell

+1

@GBK Bạn có thể đặt thời gian chờ trên chuỗi kết nối sau đó. Bạn có thể sử dụng [SqlConnectionStringBuilder] (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder.aspx) để phân tích cú pháp và sửa đổi chuỗi kết nối trước khi bạn truyền nó cho đối tượng kết nối. –

Các vấn đề liên quan