2010-09-01 15 views
14

SqlClient.SqlConnection ile bir SQL bağlantı dizesi kullanıyorum ve dizede Connection Timeout = 5 belirtiyorum, ancak hala hata vermeden önce 30 saniye bekler. Nasıl pes ettirip daha hızlı geri dönebilirim? Hızlı bir yerel ağdayım ve 30 saniye beklemek istemiyorum. Açılmayan sunucular başarısız olmak için 30 saniyedir. Bu sadece her zaman bu yerel ağ üzerinde çalışacak olan hızlı bir yardımcı programdır.SqlConnection zaman aşımı daha hızlı bir şekilde nasıl yapılır

Edit: Üzgünüz, üzgünüm. SqlConnection.Open'ın daha hızlı başarısız olmasını istiyorum. Umarım ki daha hızlı başarısız olmak istediğim sunucuların kapatılmasından kaynaklanabilir.

Edit: Ayar, bazen yalnızca başarısız olur. Sunucunun IP adresini bildiği gibi, TCP/IP ile konuşmak için (yerel değil) konuşuyor, ancak bu adreste SQL Server ile iletişim kuramıyor mu? Desenin ne olduğundan emin değilim, ancak SQL Server ile yerel olarak bağlanırken sorunu görmüyorum ve varolmayan bir sunucuya bağlanmaya çalışırken göremiyorum. Yine de, Windows 2008 güvenlik duvarının SQL Server'ı engellediği bir sunucuyla bağlantı kurmaya çalışırken gördüm.

cevap

10

çözülebileceğini çok daha çabuk böyle doğrudan bir soket bağlantısı çalışarak:

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

ben kontrol etmek bu kodu kullanmak için gidiyorum Sunucu, SQL Server bağlantı noktasında yanıt verir ve yalnızca varsa bir bağlantı açmaya çalışır.Ben (başkalarının deneyimine dayanarak) bu seviyede bile 30 saniyelik bir gecikme olacağını düşündüm, fakat makinenin şu anda hemen “bağlantıyı aktif olarak reddettiğine” dair bir mesaj alıyorum.

Düzenleme: Ve makine yoksa, bana hemen söyler. Bulduğum 30 saniyelik gecikme yok.

Düzenleme: Ağda bulunan ancak devre dışı bırakılmayan makineler hala 30 saniyeliğine başarısız olur sanırım. Güvenlik duvarları daha hızlı başarısız oluyor.

Düzeltme: Güncelleştirilmiş kod burada.

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

Güncelleştirme 2 Kendi zaman aşımınızı yuvarlamanızı öneririm. Böyle bir şey:

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

Güncelleme 1

Sadece bu kodu kullanarak kendi bilgisayarda bu test ettik:

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

ve bağlantı dizesinde Connection Timeout değerini itaat . Bu, SQL Server 2008 R2'ye karşı .NET 4 ile yapıldı. Kuşkusuz, farklı sonuçlar verebilen bir localhost bağlantısıdır, ancak sorunu kopyalayamamam anlamına gelir.

Ağ ortamınızda benzer bir kod örneğini denemenizi ve uzun zaman aşımlarını görmeye devam edip etmediğinizi görmenizi öneririz.

Eski (yanlış) cevap ben yanlış ConnectionTimeout mülkiyet ayarlanabilir olduğunu düşündüm, ama öyle değil.

Bağlantı dizesini kullanmak yerine SqlConnection.ConnectionTimeout ayarlamayı deneyin.

+0

ConnectionTimeout burada çok garip bir desen vuruyorum salt okunur bir özellik – BlueMonkMN

+0

: a parçacığı iptal olmadığı kadar bir yuva kapatmak için daha temiz gibi hissediyorum. Yerel sistemime SQL Server durduğunda bağlandığımda zaman aşımı çalışıyor gibi görünüyor. Varolmayan bir sunucuya bağlanmaya çalıştığımda çalışıyor gibi görünüyor. Ancak var olan bir sunucuya bağlanmaya çalıştığımda işe yaramaz, ancak güvenlik duvarını SQL'i engelliyor ve/veya SQL Server kurulu değil. – BlueMonkMN

+0

Buradaki ilginç bir konu: http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.adonet/topic48533.aspx. Kendi zaman aşımı mekanizmasını uygulamanızı öneririm - açık yapmayı denemek ve istediğiniz zaman aşımı süresinde başarılı olmazsa öldürmek için bir iş parçacığı döndürün. –

0

Komut Zaman Aşımı ve Bağlantı Zaman Aşımı iki farklı şeydir. Bir bağlantının açılması için bekleyeceği süre (saniye olarak) varsayılan değer 15 saniyedir. " Thats sadece SqlConnection.Open() çağırdığınızda kullanılır.

SqlCommand.CommandTimeout yapmak istediğiniz şeyi yapar.

Bu uzun gecikmelere neden olan tüm durumlar benziyor
+0

Hayır öyle değil. Açma zaman aşımı istiyorum, bir komut değil. – BlueMonkMN

+0

SqlConnection.ConnectionTimeout istediğiniz nedir – jrummell

+1

@GBK Zaman aşımını sonra bağlantı dizesinde ayarlayabilirsiniz. Bağlantı nesnesini bağlantı nesnesine iletmeden önce bağlantı dizesini ayrıştırmak ve değiştirmek için bir [SqlConnectionStringBuilder] (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder.aspx) kullanabilirsiniz. –

İlgili konular