2011-11-17 22 views
7

このコード実行している場合:このケースでConnectTimeoutが無視されるのはなぜですか?

static void Main(string[] args) 
{ 
    SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder(); 
    csb.DataSource = @"8.8.8.8"; // some inaccessible ip address 
    csb.InitialCatalog = "Tempdb"; 
    csb.IntegratedSecurity = true; 
    csb.ConnectTimeout = 1; 
    DateTime start = DateTime.Now; 
    try 
    { 
     new SqlConnection(csb.ToString()).Open(); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
    } 
    finally 
    { 
     Console.Write(string.Format("{0} seconds", DateTime.Now.Subtract(start).TotalSeconds)); 
    } 
} 

を、私はこの結果を得る:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) 
47.6097605 seconds 

私は効果があるとのconnecttimeoutプロパティを期待。では、なぜConnectTimeoutプロパティはこの場合無視されますか? (私はまた、他の人が何時に何時に見えるのか不思議です)。

更新:次の余分な行が時間間隔を26秒に短縮することに気づいた???

[email protected]"9.9.9.9"; 
+0

を掘りの価値があった考え出した場合わからないhttp://stackoverflow.com/questions/3011394/元の質問者が答えがうまくいかないとコメントしたにもかかわらず、回答が受け入れられたタイムアウトで働いていないSQL接続。O_o –

+1

catchステートメントの直後に停止時間を置いて、コードが約1秒後に例外をキャッチしているかどうかを確認します。また、次のリンクをチェックしてください:http://improve.dk/archive/2008/03/10/controlling-sqlconnection-timeouts.aspx – HardCode

+0

停止時間がcatchブロック内にあっても、コードは約47秒かかります。 –

答えて

7

EDIT:これは見えるかもしれませんのように奇妙な、私は逆コンパイル、コードの深いブレークポイントを入れて、と1にタイムアウトを設定 - >VALID < - サーバ名、私は聞かせて私のブレークポイントがそこに座って続けて、タイムアウトの期限切れの例外を期待通りに与えましたしたがって、ConnectTimeoutは、サーバーを解決して接続を待っているときだけ適用されるようです。 は、サーバーを解決してに接続しないようにします。私は経験している時間がサーバーの解像度のためであり、実際の "接続"の行為ではないと思います。少なくとも私の現在の仮説です。

リフレクターを使用して、カバーの下に何が起こっていたのかを確認しました。たぶん誰かから私はまた、ConnectTimeoutは、初期接続に影響を与えないように見えるので、ここで私たちを助けることができます。

とにかく、内部で接続を確立するためには、以下のメソッドが呼び出されます、このシーケンスでは、私は思う:

internal DbConnectionInternal CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options) 
    { 
     DbConnectionPoolGroupProviderInfo providerInfo = pool.PoolGroup.ProviderInfo; 
     DbConnectionInternal internal2 = this.CreateConnection(options, providerInfo, pool, owningConnection); 
     if (internal2 != null) 
     { 
     this.PerformanceCounters.HardConnectsPerSecond.Increment(); 
     internal2.MakePooledConnection(pool); 
     } 
     Bid.Trace("<prov.DbConnectionFactory.CreatePooledConnection|RES|CPOOL> %d#, Pooled database connection created.\n", this.ObjectID); 
     return internal2; 
    } 

そして:

protected override DbConnectionInternal CreateConnection(DbConnectionOptions options, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) 
    { 
     string instanceName; 
     SqlConnectionString str = (SqlConnectionString) options; 
     if (str.ContextConnection) 
     { 
     return this.GetContextConnection(str, poolGroupProviderInfo, owningConnection); 
     } 
     bool redirectedUserInstance = false; 
     DbConnectionPoolIdentity current = null; 
     if (str.IntegratedSecurity) 
     { 
     if (pool != null) 
     { 
      current = pool.Identity; 
     } 
     else 
     { 
      current = DbConnectionPoolIdentity.GetCurrent(); 
     } 
     } 
     if (!str.UserInstance) 
     { 
     goto Label_00F1; 
     } 
     redirectedUserInstance = true; 
     if ((pool == null) || ((pool != null) && (pool.Count <= 0))) 
     { 
     using (SqlInternalConnectionTds tds = null) 
     { 
      SqlConnectionString connectionOptions = new SqlConnectionString(str, str.DataSource, true, false); 
      tds = new SqlInternalConnectionTds(current, connectionOptions, null, "", null, false); 
      instanceName = tds.InstanceName; 
      if (!instanceName.StartsWith(@"\\.\", StringComparison.Ordinal)) 
      { 
      throw SQL.NonLocalSSEInstance(); 
      } 
      if (pool != null) 
      { 
      SqlConnectionPoolProviderInfo info2 = (SqlConnectionPoolProviderInfo) pool.ProviderInfo; 
      info2.InstanceName = instanceName; 
      } 
      goto Label_00DB; 
     } 
     } 
     SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo) pool.ProviderInfo; 
     instanceName = providerInfo.InstanceName; 
    Label_00DB: 
     str = new SqlConnectionString(str, instanceName, false, null); 
     poolGroupProviderInfo = null; 
    Label_00F1: 
     return new SqlInternalConnectionTds(current, str, poolGroupProviderInfo, "", (SqlConnection) owningConnection, redirectedUserInstance); 
    } 

、その後:

internal SqlInternalConnectionTds(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, object providerInfo, string newPassword, SqlConnection owningObject, bool redirectedUserInstance) : base(connectionOptions) 
    { 
     this._instanceName = string.Empty; 
     if (connectionOptions.UserInstance && InOutOfProcHelper.InProc) 
     { 
     throw SQL.UserInstanceNotAvailableInProc(); 
     } 
     this._identity = identity; 
     this._poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo) providerInfo; 
     this._fResetConnection = connectionOptions.ConnectionReset; 
     if (this._fResetConnection) 
     { 
     this._originalDatabase = connectionOptions.InitialCatalog; 
     this._originalLanguage = connectionOptions.CurrentLanguage; 
     } 
     RuntimeHelpers.PrepareConstrainedRegions(); 
     try 
     { 
     TimeoutTimer timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout); 
     this.OpenLoginEnlist(owningObject, timeout, connectionOptions, newPassword, redirectedUserInstance); 
     } 
     catch (OutOfMemoryException) 
     { 
     base.DoomThisConnection(); 
     throw; 
     } 
     catch (StackOverflowException) 
     { 
     base.DoomThisConnection(); 
     throw; 
     } 
     catch (ThreadAbortException) 
     { 
     base.DoomThisConnection(); 
     throw; 
     } 
     if (Bid.AdvancedOn) 
     { 
     Bid.Trace("<sc.SqlInternalConnectionTds.ctor|ADV> %d#, constructed new TDS internal connection\n", base.ObjectID); 
     } 
    } 

を既定では(フェールオーバーパートナーなし):

private void LoginNoFailover(ServerInfo serverInfo, string newPassword, bool redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout) 
    { 
     if (Bid.AdvancedOn) 
     { 
     Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, host=%ls\n", base.ObjectID, serverInfo.UserServerName); 
     } 
     int num = 100; 
     this.ResolveExtendedServerName(serverInfo, !redirectedUserInstance, owningObject); 
     while (true) 
     { 
     if (this._parser != null) 
     { 
      this._parser.Disconnect(); 
     } 
     this._parser = new TdsParser(base.ConnectionOptions.MARS, base.ConnectionOptions.Asynchronous); 
     try 
     { 
      this.AttemptOneLogin(serverInfo, newPassword, true, timeout, owningObject); 
      break; 
     } 
     catch (SqlException exception) 
     { 
      if (((this._parser == null) || (this._parser.State != TdsParserState.Closed)) || (this.IsDoNotRetryConnectError(exception.Number) || timeout.IsExpired)) 
      { 
      throw; 
      } 
      if (timeout.MillisecondsRemaining <= num) 
      { 
      throw; 
      } 
     } 
     if (this.ServerProvidedFailOverPartner != null) 
     { 
      this.LoginWithFailover(true, serverInfo, this.ServerProvidedFailOverPartner, newPassword, redirectedUserInstance, owningObject, connectionOptions, timeout); 
      return; 
     } 
     if (Bid.AdvancedOn) 
     { 
      Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, sleeping %d{milisec}\n", base.ObjectID, num); 
     } 
     Thread.Sleep(num); 
     num = (num < 500) ? (num * 2) : 0x3e8; 
     } 
     if (this.PoolGroupProviderInfo != null) 
     { 
     this.PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, this.ServerProvidedFailOverPartner); 
     } 
     base.CurrentDataSource = serverInfo.UserServerName; 
    } 

、その後:

internal void Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, bool ignoreSniOpenTimeout, long timerExpire, bool encrypt, bool trustServerCert, bool integratedSecurity) 
    { 
     if (this._state == TdsParserState.Closed) 
     { 
     this._connHandler = connHandler; 
     if (SNILoadHandle.SingletonInstance.SNIStatus != 0) 
     { 
      this.Errors.Add(this.ProcessSNIError(this._physicalStateObj)); 
      this._physicalStateObj.Dispose(); 
      this.ThrowExceptionAndWarning(); 
     } 
     if (integratedSecurity) 
     { 
      this.LoadSSPILibrary(); 
      this._sniServerUserName = new byte[s_maxSSPILength]; 
      Bid.Trace("<sc.TdsParser.Connect|SEC> SSPI authentication\n"); 
     } 
     else 
     { 
      Bid.Trace("<sc.TdsParser.Connect|SEC> SQL authentication\n"); 
     } 
     byte[] instanceName = null; 
     this._physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, integratedSecurity, this._sniServerUserName, false, this._fAsync); 
     if (this._physicalStateObj.Status != 0) 
     { 
      this.Errors.Add(this.ProcessSNIError(this._physicalStateObj)); 
      this._physicalStateObj.Dispose(); 
      Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n"); 
      this.ThrowExceptionAndWarning(); 
     } 
     this._server = serverInfo.ResolvedServerName; 
     if (connHandler.PoolGroupProviderInfo != null) 
     { 
      connHandler.PoolGroupProviderInfo.AliasCheck(serverInfo.ResolvedServerName); 
     } 
     this._state = TdsParserState.OpenNotLoggedIn; 
     this._physicalStateObj.SniContext = SniContext.Snix_PreLoginBeforeSuccessfullWrite; 
     this._physicalStateObj.TimeoutTime = timerExpire; 
     bool marsCapable = false; 
     this.SendPreLoginHandshake(instanceName, encrypt); 
     this._physicalStateObj.SniContext = SniContext.Snix_PreLogin; 
     switch (this.ConsumePreLoginHandshake(encrypt, trustServerCert, out marsCapable)) 
     { 
      case PreLoginHandshakeStatus.SphinxFailure: 
      this._fMARS = false; 
      this._physicalStateObj._sniPacket = null; 
      this._physicalStateObj.SniContext = SniContext.Snix_Connect; 
      this._physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, integratedSecurity, this._sniServerUserName, false, this._fAsync); 
      if (this._physicalStateObj.Status != 0) 
      { 
       this.Errors.Add(this.ProcessSNIError(this._physicalStateObj)); 
       Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n"); 
       this.ThrowExceptionAndWarning(); 
      } 
      break; 

      case PreLoginHandshakeStatus.InstanceFailure: 
      this._physicalStateObj.Dispose(); 
      this._physicalStateObj.SniContext = SniContext.Snix_Connect; 
      this._physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, integratedSecurity, this._sniServerUserName, true, this._fAsync); 
      if (this._physicalStateObj.Status != 0) 
      { 
       this.Errors.Add(this.ProcessSNIError(this._physicalStateObj)); 
       Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n"); 
       this.ThrowExceptionAndWarning(); 
      } 
      this.SendPreLoginHandshake(instanceName, encrypt); 
      if (this.ConsumePreLoginHandshake(encrypt, trustServerCert, out marsCapable) == PreLoginHandshakeStatus.InstanceFailure) 
      { 
       Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n"); 
       throw SQL.InstanceFailure(); 
      } 
      break; 
     } 
     if (this._fMARS && marsCapable) 
     { 
      this._sessionPool = new TdsParserSessionPool(this); 
     } 
     else 
     { 
      this._fMARS = false; 
     } 
     } 
    } 

私は一緒にどのようにこのすべての部分を確認していないが、infiniteTimeoutは本当のようです。

これは、任意のに役立ちますが、私はそれは私がsmilar問題を見

enter image description here

enter image description here

+0

よくできました。私はあなたが正しいと思います。そして、取り除くべき教訓は、Open()を呼び出すと、connectiontimeout秒後に応答を得ることができないということです(プロパティをほとんど役に立たないようにする)。 @HardCodeはMark S. Rasmussenの記事(http://improve.dk/archive/2008/03/10/controlling-sqlconnection-timeouts.aspx)を指しています。これにはDIYタイムアウトがあります。 –

+0

ところで、私はBIDトレースを走らせました(セットアップが簡単ではありません!)そして、TCP/IPとNamed Pipesの両方を試してみることに気付きました。私はその話にどのように当てはまるのか分かりません... –

+0

うん、それは混乱しますが、私は接続タイムアウトがサーバを解決できるまで強制されていないと思います。サーバーが解決されると、接続の継続時間が開始されます。マイクロソフトはおそらくこれをもう少し明確にしなければなりません。 – kd7

関連する問題