Ho usato il riflettore per vedere cosa stava succedendo sotto le coperte. Forse qualcuno da Microsoft può aiutarci qui, perché ho anche scoperto che ConnectTimeout sembra non avere alcun effetto sulla connessione iniziale.
Comunque internamente per stabilire la connessione, i seguenti metodi vengono chiamati, in questa sequenza penso:
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;
}
E poi:
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);
}
e poi:
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);
}
}
e quindi, per impostazione predefinita (senza partner Failover):
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;
}
e poi:
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;
}
}
}
io non sono sicuro di come questo tutti i pezzi insieme, ma infiniteTimeout sembra essere vero.
Non sono sicuro se questo aiuta qualsiasi, ma ho pensato che valeva la pena scavare attraverso
ho visto un problema smilar http://stackoverflow.com/questions/3011394/ timeout-not-working-in-sql-connection in cui è stata accettata una risposta anche se il richiedente originale ha commentato che la risposta non ha funzionato.O_o –
Metti il tempo di arresto subito dopo l'istruzione catch per vedere se il codice sta recuperando l'eccezione dopo circa 1 secondo. Inoltre, consulta questo link: http://improve.dk/archive/2008/03/10/controlling-sqlconnection-timeouts.aspx – HardCode
Il codice impiega circa 47 secondi anche se il tempo di arresto è nel blocco catch. –