internal ServerInfo(SqlConnectionString userOptions, string serverName) { this.UserServerName = serverName ?? string.Empty; this.UserProtocol = userOptions.NetworkLibrary; this.ResolvedDatabaseName = userOptions.InitialCatalog; this.PreRoutingServerName = null; }
private System.Security.PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner) { string keywordToReplace; // RULES FOR CONSTRUCTING THE CONNECTION STRING TO DEMAND ON: // // 1) If no Failover Partner was specified in the original string: // // Server=actualFailoverPartner // // 2) If Failover Partner was specified in the original string: // // Server=originalValue; Failover Partner=actualFailoverPartner // // NOTE: in all cases, when we get a failover partner name from // the server, we will use that name over what was specified // in the original connection string. if (null == userConnectionOptions[SqlConnectionString.KEY.FailoverPartner]) { keywordToReplace = SqlConnectionString.KEY.Data_Source; } else { keywordToReplace = SqlConnectionString.KEY.FailoverPartner; } string failoverConnectionString = userConnectionOptions.ExpandKeyword(keywordToReplace, actualFailoverPartner); return (new SqlConnectionString(failoverConnectionString)).CreatePermissionSet(); }
// This c-tor is used to create SSE and user instance connection strings when user instance is set to true // BUG (VSTFDevDiv) 479687: Using TransactionScope with Linq2SQL against user instances fails with "connection has been broken" message internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance) : base(connectionOptions) { _integratedSecurity = connectionOptions._integratedSecurity; _encrypt = connectionOptions._encrypt; _mars = connectionOptions._mars; _persistSecurityInfo = connectionOptions._persistSecurityInfo; _pooling = connectionOptions._pooling; _replication = connectionOptions._replication; _userInstance = userInstance; _connectTimeout = connectionOptions._connectTimeout; _loadBalanceTimeout = connectionOptions._loadBalanceTimeout; _maxPoolSize = connectionOptions._maxPoolSize; _minPoolSize = connectionOptions._minPoolSize; _multiSubnetFailover = connectionOptions._multiSubnetFailover; _packetSize = connectionOptions._packetSize; _applicationName = connectionOptions._applicationName; _attachDBFileName = connectionOptions._attachDBFileName; _currentLanguage = connectionOptions._currentLanguage; _dataSource = dataSource; _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource); _failoverPartner = connectionOptions._failoverPartner; _initialCatalog = connectionOptions._initialCatalog; _password = connectionOptions._password; _userID = connectionOptions._userID; _workstationId = connectionOptions._workstationId; _typeSystemVersion = connectionOptions._typeSystemVersion; _applicationIntent = connectionOptions._applicationIntent; _connectRetryCount = connectionOptions._connectRetryCount; _connectRetryInterval = connectionOptions._connectRetryInterval; ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source); }
internal SqlClientPermission(SqlConnectionString constr) : base(constr) { if ((constr == null) || constr.IsEmpty) { base.Add(ADP.StrEmpty, ADP.StrEmpty, KeyRestrictionBehavior.AllowOnly); } }
internal SqlClientPermission(SqlConnectionString constr) : base(constr) { if ((constr == null) || constr.IsEmpty) { base.Add(ADP.StrEmpty, ADP.StrEmpty, KeyRestrictionBehavior.AllowOnly); } }
internal ServerInfo(SqlConnectionString userOptions, string serverName) { this.UserServerName = serverName ?? string.Empty; this.UserProtocol = userOptions.NetworkLibrary; this.ResolvedDatabaseName = userOptions.InitialCatalog; this.PreRoutingServerName = null; }
static internal SqlConnectionString ParseString(string connectionString) { SqlConnectionString constr = null; if (!ADP.IsEmpty(connectionString)) { constr = (DBConnectionString.CacheQuery(connectionString, _sqlClientParseCache) as SqlConnectionString); if (null == constr) { #if USECRYPTO string encrypted = null/*Crypto.EncryptString(connectionString)*/; string hashvalue = (null == encrypted) ? Crypto.ComputeHash(connectionString) : encrypted; constr = (DBConnectionString.CacheQuery(hashvalue, _sqlClientParseCache) as SqlConnectionString); if (null == constr) { constr = new SqlConnectionString(connectionString, encrypted); #else constr = new SqlConnectionString(connectionString); #endif if (constr.ShouldCache()) { #if USECRYPTO if (!constr.IsEncrypted) { hashvalue = connectionString; } CacheAdd(hashvalue, constr, ref _sqlClientParseCache); #else CacheAdd(connectionString, constr, ref _sqlClientParseCache); #endif } #if USECRYPTO } #endif } } return constr; }
protected override DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions(DbConnectionOptions connectionOptions) { SqlConnectionString opt = (SqlConnectionString)connectionOptions; DbConnectionPoolGroupOptions poolingOptions = null; if (opt.Pooling) { // never pool context connections. int connectionTimeout = opt.ConnectTimeout; if ((0 < connectionTimeout) && (connectionTimeout < int.MaxValue / 1000)) { connectionTimeout *= 1000; } else if (connectionTimeout >= int.MaxValue / 1000) { connectionTimeout = int.MaxValue; } poolingOptions = new DbConnectionPoolGroupOptions( opt.IntegratedSecurity, opt.MinPoolSize, opt.MaxPoolSize, connectionTimeout, opt.LoadBalanceTimeout, opt.Enlist); } return(poolingOptions); }
override protected DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions(DbConnectionOptions connectionOptions) { SqlConnectionString opt = (SqlConnectionString)connectionOptions; DbConnectionPoolGroupOptions poolingOptions = null; if (!opt.ContextConnection && opt.Pooling) // never pool context connections. { int connectionTimeout = opt.ConnectTimeout; if ((0 < connectionTimeout) && (connectionTimeout < Int32.MaxValue / 1000)) { connectionTimeout *= 1000; } else if (connectionTimeout >= Int32.MaxValue / 1000) { connectionTimeout = Int32.MaxValue; } poolingOptions = new DbConnectionPoolGroupOptions( opt.IntegratedSecurity || opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated, opt.MinPoolSize, opt.MaxPoolSize, connectionTimeout, opt.LoadBalanceTimeout, opt.Enlist); } return(poolingOptions); }
public void Close() { // this method will actually close the internal connection and dipose it, this // should only be called by a non-pooled sqlconnection, or by the object pooler // when it deems an object should be destroyed // it's possible to have a connection finalizer, internal connection finalizer, // and the object pool destructor calling this method at the same time, so // we need to provide some synchronization if (_fConnectionOpen) { if (Interlocked.CompareExchange(ref _lock, 1, 0) == 0) { if (_fConnectionOpen) { if (_fIsPooled) { // PerfCounters - on close of pooled connection, decrement count SQL.DecrementPooledConnectionCount(); } try { try { _parser.Disconnect(); // UNDONE: GC.SuppressFinalize causes a permission demand? //GC.SuppressFinalize(_parser); } finally { // _connectionWeakRef= // close will always close, even if exception is thrown // remember to null out any object references _connectionWeakRef = null; _connectionOptions = null; _parser = null; _loginAck = null; _fConnectionOpen = false; // mark internal connection as closed _fUsableState = false; // mark internal connection as unusable _pool = null; _dtcAddress = null; _transactionGuid = Guid.Empty; _transactionExport = null; // always release the lock //Interlocked.CompareExchange(ref _lock, 0, 1); _lock = 0; } } catch { // MDAC 80973 throw; } } else { // release lock in case where connection already closed //Interlocked.CompareExchange(ref _lock, 0, 1); _lock = 0; } } } }
// this constructor is called by the implicit object pooler public SqlInternalConnection(SqlConnectionString connectionOptions, ConnectionPool pool, bool fCheckLifetime, TimeSpan lifetime, bool fResetConnection, string originalDatabase, string originalLanguage) { // clone the hashtable, since this is pooled - should not use same reference _connectionOptions = connectionOptions.Clone(); _fIsPooled = true; _pool = pool; _fCheckLifetime = fCheckLifetime; _lifetime = lifetime; _fResetConnection = fResetConnection; _originalDatabase = originalDatabase; _originalLanguage = originalLanguage; this.OpenAndLogin(); // PerfCounters SQL.IncrementPooledConnectionCount(); SQL.PossibleIncrementPeakPoolConnectionCount(); // let activate handle distributed transaction enlistment // obtain the time of construction, if fCheckLifetime if (_fCheckLifetime) { _createTime = DateTime.UtcNow; } }
protected override DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous) { Debug.Assert(!string.IsNullOrEmpty(connectionString), "empty connectionString"); SqlConnectionString result = new SqlConnectionString(connectionString); return(result); }
private System.Security.PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner) { string keywordToReplace; // RULES FOR CONSTRUCTING THE CONNECTION STRING TO DEMAND ON: // // 1) If no Failover Partner was specified in the original string: // // Server=actualFailoverPartner // // 2) If Failover Partner was specified in the original string: // // Server=originalValue; Failover Partner=actualFailoverPartner // // NOTE: in all cases, when we get a failover partner name from // the server, we will use that name over what was specified // in the original connection string. if (null == userConnectionOptions[SqlConnectionString.KEY.FailoverPartner]) { keywordToReplace = SqlConnectionString.KEY.Data_Source; } else { keywordToReplace = SqlConnectionString.KEY.FailoverPartner; } string failoverConnectionString = userConnectionOptions.ExpandKeyword(keywordToReplace, actualFailoverPartner); return((new SqlConnectionString(failoverConnectionString)).CreatePermissionSet()); }
private SqlConnectionString(SqlConnectionString value) : base(value, false) { // Clone _permission = value._permission; _integratedSecurity = value._integratedSecurity; _connectionReset = value._connectionReset; _enlist = value._enlist; _encrypt = value._encrypt; _persistSecurityInfo = value._persistSecurityInfo; _pooling = value._pooling; _connectionLifeTime = value._connectionLifeTime; _connectTimeout = value._connectTimeout; _maxPoolSize = value._maxPoolSize; _minPoolSize = value._minPoolSize; _packetSize = value._packetSize; _applicationName = value._applicationName; _attachDBFileName = value._attachDBFileName; _currentLanguage = value._currentLanguage; _dataSource = value._dataSource; _initialCatalog = value._initialCatalog; _networkLibrary = value._networkLibrary; _userID = value._userID; _password = value._password; _workstationId = value._workstationId; }
internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions) { this._failoverPartner = connectionOptions.FailoverPartner; if (ADP.IsEmpty(this._failoverPartner)) { this._failoverPartner = null; } }
internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions) { this._failoverPartner = connectionOptions.FailoverPartner; if (ADP.IsEmpty(this._failoverPartner)) { this._failoverPartner = null; } }
// This method will be called once connection string is set or changed. private void CacheConnectionStringProperties() { SqlConnectionString connString = ConnectionOptions as SqlConnectionString; if (connString != null) { _connectRetryCount = connString.ConnectRetryCount; } }
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 SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions) { // This is for the case where the user specified the failover partner // in the connection string and we have not yet connected to get the // env change. _failoverPartner = connectionOptions.FailoverPartner; if (ADP.IsEmpty(_failoverPartner)) { _failoverPartner = null; } }
// Does this connection uses old style of clear userID or Password in connection string? private bool UsesClearUserIdOrPassword(SqlConnectionString opt) { bool result = false; if (null != opt) { result = (!ADP.IsEmpty(opt.UserID) || !ADP.IsEmpty(opt.Password)); } return(result); }
private bool TryOpen(TaskCompletionSource <DbConnectionInternal> retry) { SqlConnectionString connectionOptions = (SqlConnectionString)ConnectionOptions; // Fail Fast in case an application is trying to enlist the SqlConnection in a Transaction Scope. if (connectionOptions.Enlist && ADP.GetCurrentTransaction() != null) { throw ADP.AmbientTransactionIsNotSupported(); } _applyTransientFaultHandling = (retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0); if (ForceNewConnection) { if (!InnerConnection.TryReplaceConnection(this, ConnectionFactory, retry, UserConnectionOptions)) { return(false); } } else { if (!InnerConnection.TryOpenConnection(this, ConnectionFactory, retry, UserConnectionOptions)) { return(false); } } // does not require GC.KeepAlive(this) because of OnStateChange var tdsInnerConnection = (SqlInternalConnectionTds)InnerConnection; Debug.Assert(tdsInnerConnection.Parser != null, "Where's the parser?"); if (!tdsInnerConnection.ConnectionOptions.Pooling) { // For non-pooled connections, we need to make sure that the finalizer does actually run to avoid leaking SNI handles GC.ReRegisterForFinalize(this); } // The _statistics can change with StatisticsEnabled. Copying to a local variable before checking for a null value. SqlStatistics statistics = _statistics; if (StatisticsEnabled || (s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterExecuteCommand) && statistics != null)) { ADP.TimerCurrent(out _statistics._openTimestamp); tdsInnerConnection.Parser.Statistics = _statistics; } else { tdsInnerConnection.Parser.Statistics = null; _statistics = null; // in case of previous Open/Close/reset_CollectStats sequence } return(true); }
internal SqlInternalConnectionSmi(SqlConnectionString connectionOptions, SmiContext smiContext) : base(connectionOptions) { this._smiContext = smiContext; this._smiContext.OutOfScope += new EventHandler(this.OnOutOfScope); this._smiConnection = this._smiContext.ContextConnection; this._smiEventSink = new EventSink(this); if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionSmi.ctor|ADV> %d#, constructed new SMI internal connection\n", base.ObjectID); } }
internal SqlInternalConnectionSmi(SqlConnectionString connectionOptions, SmiContext smiContext) : base(connectionOptions) { this._smiContext = smiContext; this._smiContext.OutOfScope += new EventHandler(this.OnOutOfScope); this._smiConnection = this._smiContext.ContextConnection; this._smiEventSink = new EventSink(this); if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionSmi.ctor|ADV> %d#, constructed new SMI internal connection\n", base.ObjectID); } }
internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions) { // This is for the case where the user specified the failover partner // in the connection string and we have not yet connected to get the // env change. _failoverPartner = connectionOptions.FailoverPartner; if (ADP.IsEmpty(_failoverPartner)) { _failoverPartner = null; } }
// This c-tor is used to create SSE and user instance connection strings when user instance is set to true // internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance, bool?setEnlistValue) : base(connectionOptions) { _integratedSecurity = connectionOptions._integratedSecurity; _connectionReset = connectionOptions._connectionReset; _contextConnection = connectionOptions._contextConnection; _encrypt = connectionOptions._encrypt; if (setEnlistValue.HasValue) { _enlist = setEnlistValue.Value; } else { _enlist = connectionOptions._enlist; } _mars = connectionOptions._mars; _persistSecurityInfo = connectionOptions._persistSecurityInfo; _pooling = connectionOptions._pooling; _replication = connectionOptions._replication; _userInstance = userInstance; _connectTimeout = connectionOptions._connectTimeout; _loadBalanceTimeout = connectionOptions._loadBalanceTimeout; _poolBlockingPeriod = connectionOptions._poolBlockingPeriod; _maxPoolSize = connectionOptions._maxPoolSize; _minPoolSize = connectionOptions._minPoolSize; _multiSubnetFailover = connectionOptions._multiSubnetFailover; _transparentNetworkIPResolution = connectionOptions._transparentNetworkIPResolution; _packetSize = connectionOptions._packetSize; _applicationName = connectionOptions._applicationName; _attachDBFileName = connectionOptions._attachDBFileName; _currentLanguage = connectionOptions._currentLanguage; _dataSource = dataSource; _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource); _failoverPartner = connectionOptions._failoverPartner; _initialCatalog = connectionOptions._initialCatalog; _password = connectionOptions._password; _userID = connectionOptions._userID; _networkLibrary = connectionOptions._networkLibrary; _workstationId = connectionOptions._workstationId; _expandedAttachDBFilename = connectionOptions._expandedAttachDBFilename; _typeSystemVersion = connectionOptions._typeSystemVersion; _typeSystemAssemblyVersion = connectionOptions._typeSystemAssemblyVersion; _transactionBinding = connectionOptions._transactionBinding; _applicationIntent = connectionOptions._applicationIntent; _connectRetryCount = connectionOptions._connectRetryCount; _connectRetryInterval = connectionOptions._connectRetryInterval; _authType = connectionOptions._authType; _columnEncryptionSetting = connectionOptions._columnEncryptionSetting; _enclaveAttestationUrl = connectionOptions._enclaveAttestationUrl; ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source); }
private PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner) { string str; if (userConnectionOptions["failover partner"] == null) { str = "data source"; } else { str = "failover partner"; } return new SqlConnectionString(userConnectionOptions.ExpandKeyword(str, actualFailoverPartner)).CreatePermissionSet(); }
private PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner) { string str; if (userConnectionOptions["failover partner"] == null) { str = "data source"; } else { str = "failover partner"; } return(new SqlConnectionString(userConnectionOptions.ExpandKeyword(str, actualFailoverPartner)).CreatePermissionSet()); }
internal static SqlConnectionString FindSqlConnectionOptions(SqlConnectionPoolKey key) { SqlConnectionString connectionOptions = (SqlConnectionString)SingletonInstance.FindConnectionOptions(key); if (null == connectionOptions) { connectionOptions = new SqlConnectionString(key.ConnectionString); } if (connectionOptions.IsEmpty) { throw ADP.NoConnectionString(); } return(connectionOptions); }
internal static SqlConnectionString FindSqlConnectionOptions(string connectionString) { SqlConnectionString str = (SqlConnectionString)SingletonInstance.FindConnectionOptions(connectionString); if (str == null) { str = new SqlConnectionString(connectionString); } if (str.IsEmpty) { throw ADP.NoConnectionString(); } return(str); }
internal ServerInfo(SqlConnectionString userOptions, RoutingInfo routing, string preRoutingServerName) { if ((routing == null) || (routing.ServerName == null)) { this.UserServerName = string.Empty; } else { this.UserServerName = string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[] { routing.ServerName, routing.Port }); } this.PreRoutingServerName = preRoutingServerName; this.UserProtocol = "tcp"; this.SetDerivedNames(this.UserProtocol, this.UserServerName); this.ResolvedDatabaseName = userOptions.InitialCatalog; }
/// <include file='doc\SqlClientPermission.uex' path='docs/doc[@for="SqlClientPermission.Add"]/*' /> override public void Add(string connectionString, string restrictions, KeyRestrictionBehavior behavior) { switch (behavior) { case KeyRestrictionBehavior.PreventUsage: case KeyRestrictionBehavior.AllowOnly: break; default: throw ADP.Argument("value"); } DBConnectionString entry = new SqlConnectionString(connectionString, restrictions, behavior); // MDAC 85142 base.AddPermissionEntry(entry); }
internal ServerInfo(SqlConnectionString userOptions, RoutingInfo routing, string preRoutingServerName) { if ((routing == null) || (routing.ServerName == null)) { this.UserServerName = string.Empty; } else { this.UserServerName = string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[] { routing.ServerName, routing.Port }); } this.PreRoutingServerName = preRoutingServerName; this.UserProtocol = "tcp"; this.SetDerivedNames(this.UserProtocol, this.UserServerName); this.ResolvedDatabaseName = userOptions.InitialCatalog; }
private TransactionWrapper _transaction; // cache the ITransaction in the case of manual enlistment // this constructor is called by SqlConnection, and is not implicitly pooled public SqlInternalConnection(SqlConnection connection, SqlConnectionString connectionOptions) { _connectionWeakRef = new WeakReference(connection); // use the same hashtable reference since non-pooled _connectionOptions = connectionOptions; // cloned by SqlConnection _fIsPooled = false; this.OpenAndLogin(); // for non-pooled connections, enlist in a distributed transaction // if present - and user specified to enlist if (_connectionOptions.Enlist) { this.EnlistDistributedTransaction(); } }
private SqlInternalConnectionSmi GetContextConnection(SqlConnectionString options, object providerInfo, DbConnection owningConnection) { SmiContext currentContext = SmiContextFactory.Instance.GetCurrentContext(); SqlInternalConnectionSmi contextValue = (SqlInternalConnectionSmi)currentContext.GetContextValue(0); if ((contextValue == null) || contextValue.IsConnectionDoomed) { if (contextValue != null) { contextValue.Dispose(); } contextValue = new SqlInternalConnectionSmi(options, currentContext); currentContext.SetContextValue(0, contextValue); } contextValue.Activate(); return(contextValue); }
private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnection owningObject) { if (serverInfo.ExtendedServerName == null) { string userServerName = serverInfo.UserServerName; string userProtocol = serverInfo.UserProtocol; if (aliasLookup) { TdsParserStaticMethods.AliasRegistryLookup(ref userServerName, ref userProtocol); if ((owningObject != null) && ((SqlConnectionString)owningObject.UserConnectionOptions).EnforceLocalHost) { SqlConnectionString.VerifyLocalHostAndFixup(ref userServerName, true, true); } } serverInfo.SetDerivedNames(userProtocol, userServerName); } }
internal SqlInternalConnectionSmi(SqlConnectionString connectionOptions, SmiContext smiContext) : base(connectionOptions) { Debug.Assert(null != smiContext, "null smiContext?"); _smiContext = smiContext; _smiContext.OutOfScope += new EventHandler(OnOutOfScope); _smiConnection = _smiContext.ContextConnection; Debug.Assert(null != _smiConnection, "null SmiContext.ContextConnection?"); _smiEventSink = new EventSink(this); if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionSmi.ctor|ADV> %d#, constructed new SMI internal connection\n", ObjectID); } }
public static void ChangePassword(string connectionString, string newPassword) { IntPtr ptr; Bid.ScopeEnter(out ptr, "<sc.SqlConnection.ChangePassword|API>"); try { if (ADP.IsEmpty(connectionString)) { throw SQL.ChangePasswordArgumentMissing("connectionString"); } if (ADP.IsEmpty(newPassword)) { throw SQL.ChangePasswordArgumentMissing("newPassword"); } if (0x80 < newPassword.Length) { throw ADP.InvalidArgumentLength("newPassword", 0x80); } SqlConnectionString connectionOptions = SqlConnectionFactory.FindSqlConnectionOptions(connectionString); if (connectionOptions.IntegratedSecurity) { throw SQL.ChangePasswordConflictsWithSSPI(); } if (!ADP.IsEmpty(connectionOptions.AttachDBFilename)) { throw SQL.ChangePasswordUseOfUnallowedKey("attachdbfilename"); } if (connectionOptions.ContextConnection) { throw SQL.ChangePasswordUseOfUnallowedKey("context connection"); } connectionOptions.CreatePermissionSet().Demand(); using (SqlInternalConnectionTds tds = new SqlInternalConnectionTds(null, connectionOptions, null, newPassword, null, false)) { if (!tds.IsYukonOrNewer) { throw SQL.ChangePasswordRequiresYukon(); } } SqlConnectionFactory.SingletonInstance.ClearPool(connectionString); } finally { Bid.ScopeLeave(ref ptr); } }
private bool TryOpen(TaskCompletionSource <DbConnectionInternal> retry) { SqlConnectionString connectionOptions = (SqlConnectionString)ConnectionOptions; _applyTransientFaultHandling = (retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0); if (ForceNewConnection) { if (!InnerConnection.TryReplaceConnection(this, ConnectionFactory, retry, UserConnectionOptions)) { return(false); } } else { if (!InnerConnection.TryOpenConnection(this, ConnectionFactory, retry, UserConnectionOptions)) { return(false); } } // does not require GC.KeepAlive(this) because of OnStateChange var tdsInnerConnection = (SqlInternalConnectionTds)InnerConnection; Debug.Assert(tdsInnerConnection.Parser != null, "Where's the parser?"); if (!tdsInnerConnection.ConnectionOptions.Pooling) { // For non-pooled connections, we need to make sure that the finalizer does actually run to avoid leaking SNI handles GC.ReRegisterForFinalize(this); } if (StatisticsEnabled || s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterExecuteCommand)) { ADP.TimerCurrent(out _statistics._openTimestamp); tdsInnerConnection.Parser.Statistics = _statistics; } else { tdsInnerConnection.Parser.Statistics = null; _statistics = null; // in case of previous Open/Close/reset_CollectStats sequence } return(true); }
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); } }
internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner) { if (this.UseFailoverPartner != actualUseFailoverPartner) { Bid.Trace("<sc.SqlConnectionPoolGroupProviderInfo|INFO> Failover detected. failover partner='%ls'. Clearing PoolGroup\n", actualFailoverPartner); base.PoolGroup.Clear(); this._useFailoverPartner = actualUseFailoverPartner; } if (!this._useFailoverPartner && (this._failoverPartner != actualFailoverPartner)) { PermissionSet set = this.CreateFailoverPermission(userConnectionOptions, actualFailoverPartner); lock (this) { if (this._failoverPartner != actualFailoverPartner) { this._failoverPartner = actualFailoverPartner; this._failoverPermissionSet = set; } } } }
internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner) { if (UseFailoverPartner != actualUseFailoverPartner) { base.PoolGroup.Clear(); _useFailoverPartner = actualUseFailoverPartner; } // Only construct a new permission set when we're connecting to the // primary data source, not the failover partner. if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner) { // NOTE: we optimisitically generate the permission set to keep // lock short, but we only do this when we get a new // failover partner. lock (this) { if (_failoverPartner != actualFailoverPartner) { _failoverPartner = actualFailoverPartner; } } } }
// although the new password is generally not used it must be passed to the c'tor // the new Login7 packet will always write out the new password (or a length of zero and no bytes if not present) // internal SqlInternalConnectionTds( DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, object providerInfo, bool redirectedUserInstance, SqlConnectionString userConnectionOptions = null, // NOTE: userConnectionOptions may be different to connectionOptions if the connection string has been expanded (see SqlConnectionString.Expand) SessionData reconnectSessionData = null) : base(connectionOptions) { #if DEBUG if (reconnectSessionData != null) { reconnectSessionData._debugReconnectDataApplied = true; } #endif Debug.Assert(reconnectSessionData == null || connectionOptions.ConnectRetryCount > 0, "Reconnect data supplied with CR turned off"); if (connectionOptions.ConnectRetryCount > 0) { _recoverySessionData = reconnectSessionData; if (reconnectSessionData == null) { _currentSessionData = new SessionData(); } else { _currentSessionData = new SessionData(_recoverySessionData); _originalDatabase = _recoverySessionData._initialDatabase; _originalLanguage = _recoverySessionData._initialLanguage; } } _identity = identity; _poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo)providerInfo; _fResetConnection = connectionOptions.ConnectionReset; if (_fResetConnection && _recoverySessionData == null) { _originalDatabase = connectionOptions.InitialCatalog; _originalLanguage = connectionOptions.CurrentLanguage; } _timeoutErrorInternal = new SqlConnectionTimeoutErrorInternal(); _parserLock.Wait(canReleaseFromAnyThread: false); ThreadHasParserLockForClose = true; // In case of error, let ourselves know that we already own the parser lock try { var timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout); OpenLoginEnlist(timeout, connectionOptions, redirectedUserInstance); } finally { ThreadHasParserLockForClose = false; _parserLock.Release(); } }
// although the new password is generally not used it must be passed to the c'tor // the new Login7 packet will always write out the new password (or a length of zero and no bytes if not present) // internal SqlInternalConnectionTds( DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, object providerInfo, string newPassword, SecureString newSecurePassword, bool redirectedUserInstance, SqlConnectionString userConnectionOptions = null, // NOTE: userConnectionOptions may be different to connectionOptions if the connection string has been expanded (see SqlConnectionString.Expand) SessionData reconnectSessionData = null, DbConnectionPool pool = null, string accessToken = null, bool applyTransientFaultHandling = false ) : base(connectionOptions) { #if DEBUG if (reconnectSessionData != null) { reconnectSessionData._debugReconnectDataApplied = true; } try { // use this to help validate this object is only created after the following permission has been previously demanded in the current codepath if (userConnectionOptions != null) { // As mentioned above, userConnectionOptions may be different to connectionOptions, so we need to demand on the correct connection string userConnectionOptions.DemandPermission(); } else { connectionOptions.DemandPermission(); } } catch(System.Security.SecurityException) { System.Diagnostics.Debug.Assert(false, "unexpected SecurityException for current codepath"); throw; } #endif Debug.Assert(reconnectSessionData == null || connectionOptions.ConnectRetryCount > 0, "Reconnect data supplied with CR turned off"); _dbConnectionPool = pool; if (connectionOptions.ConnectRetryCount > 0) { _recoverySessionData = reconnectSessionData; if (reconnectSessionData == null) { _currentSessionData = new SessionData(); } else { _currentSessionData = new SessionData(_recoverySessionData); _originalDatabase = _recoverySessionData._initialDatabase; _originalLanguage = _recoverySessionData._initialLanguage; } } if (connectionOptions.UserInstance && InOutOfProcHelper.InProc) { throw SQL.UserInstanceNotAvailableInProc(); } if (accessToken != null) { _accessTokenInBytes = System.Text.Encoding.Unicode.GetBytes(accessToken); } _identity = identity; Debug.Assert(newSecurePassword != null || newPassword != null, "cannot have both new secure change password and string based change password to be null"); Debug.Assert(credential == null || (String.IsNullOrEmpty(connectionOptions.UserID) && String.IsNullOrEmpty(connectionOptions.Password)), "cannot mix the new secure password system and the connection string based password"); Debug.Assert(credential == null || !connectionOptions.IntegratedSecurity, "Cannot use SqlCredential and Integrated Security"); Debug.Assert(credential == null || !connectionOptions.ContextConnection, "Cannot use SqlCredential with context connection"); _poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo)providerInfo; _fResetConnection = connectionOptions.ConnectionReset; if (_fResetConnection && _recoverySessionData == null) { _originalDatabase = connectionOptions.InitialCatalog; _originalLanguage = connectionOptions.CurrentLanguage; } timeoutErrorInternal = new SqlConnectionTimeoutErrorInternal(); _credential = credential; _parserLock.Wait(canReleaseFromAnyThread:false); ThreadHasParserLockForClose = true; // In case of error, let ourselves know that we already own the parser lock RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG _timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout); // If transient fault handling is enabled then we can retry the login upto the ConnectRetryCount. int connectionEstablishCount = applyTransientFaultHandling ? connectionOptions.ConnectRetryCount + 1 : 1; int transientRetryIntervalInMilliSeconds = connectionOptions.ConnectRetryInterval * 1000; // Max value of transientRetryInterval is 60*1000 ms. The max value allowed for ConnectRetryInterval is 60 for (int i = 0; i < connectionEstablishCount; i++) { try { OpenLoginEnlist(_timeout, connectionOptions, credential, newPassword, newSecurePassword, redirectedUserInstance); break; } catch (SqlException sqlex) { if (i + 1 == connectionEstablishCount || !applyTransientFaultHandling || _timeout.IsExpired || _timeout.MillisecondsRemaining < transientRetryIntervalInMilliSeconds || !IsTransientError(sqlex)) { throw sqlex; } else { Thread.Sleep(transientRetryIntervalInMilliSeconds); } } } } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException) { DoomThisConnection(); throw; } catch (System.StackOverflowException) { DoomThisConnection(); throw; } catch (System.Threading.ThreadAbortException) { DoomThisConnection(); throw; } finally { ThreadHasParserLockForClose = false; _parserLock.Release(); } if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.ctor|ADV> %d#, constructed new TDS internal connection\n", ObjectID); } }
// Initialize server info from connection options, but override DataSource with given server name internal ServerInfo(SqlConnectionString userOptions, RoutingInfo routing, string preRoutingServerName) { //----------------- // Preconditions Debug.Assert(null != userOptions && null!=routing); //----------------- //Method body Debug.Assert(routing.ServerName != null, "server name should never be null"); if (routing == null || routing.ServerName == null) { UserServerName = string.Empty; // ensure user server name is not null } else { UserServerName = string.Format(CultureInfo.InvariantCulture, "{0},{1}", routing.ServerName, routing.Port); } PreRoutingServerName = preRoutingServerName; UserProtocol = TdsEnums.TCP; SetDerivedNames(UserProtocol, UserServerName); ResolvedDatabaseName = userOptions.InitialCatalog; }
// This c-tor is used to create SSE and user instance connection strings when user instance is set to true // internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance, bool? setEnlistValue) : base(connectionOptions) { _integratedSecurity = connectionOptions._integratedSecurity; _connectionReset = connectionOptions._connectionReset; _contextConnection = connectionOptions._contextConnection; _encrypt = connectionOptions._encrypt; if (setEnlistValue.HasValue) { _enlist = setEnlistValue.Value; } else { _enlist = connectionOptions._enlist; } _mars = connectionOptions._mars; _persistSecurityInfo = connectionOptions._persistSecurityInfo; _pooling = connectionOptions._pooling; _replication = connectionOptions._replication; _userInstance = userInstance; _connectTimeout = connectionOptions._connectTimeout; _loadBalanceTimeout = connectionOptions._loadBalanceTimeout; _maxPoolSize = connectionOptions._maxPoolSize; _minPoolSize = connectionOptions._minPoolSize; _multiSubnetFailover = connectionOptions._multiSubnetFailover; _packetSize = connectionOptions._packetSize; _applicationName = connectionOptions._applicationName; _attachDBFileName = connectionOptions._attachDBFileName; _currentLanguage = connectionOptions._currentLanguage; _dataSource = dataSource; _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource); _failoverPartner = connectionOptions._failoverPartner; _initialCatalog = connectionOptions._initialCatalog; _password = connectionOptions._password; _userID = connectionOptions._userID; _networkLibrary = connectionOptions._networkLibrary; _workstationId = connectionOptions._workstationId; _expandedAttachDBFilename = connectionOptions._expandedAttachDBFilename; _typeSystemVersion = connectionOptions._typeSystemVersion; _typeSystemAssemblyVersion =connectionOptions._typeSystemAssemblyVersion; _transactionBinding = connectionOptions._transactionBinding; _applicationIntent = connectionOptions._applicationIntent; _connectRetryCount = connectionOptions._connectRetryCount; _connectRetryInterval = connectionOptions._connectRetryInterval; _authType = connectionOptions._authType; _columnEncryptionSetting = connectionOptions._columnEncryptionSetting; ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source); }
override protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) { SqlConnectionString opt = (SqlConnectionString)options; SqlConnectionPoolKey key = (SqlConnectionPoolKey) poolKey; SqlInternalConnection result = null; SessionData recoverySessionData = null; SqlConnectionString userOpt = null; if (userOptions != null) { userOpt = (SqlConnectionString)userOptions; } else if (owningConnection != null) { userOpt = (SqlConnectionString)(((SqlConnection)owningConnection).UserConnectionOptions); } if (owningConnection != null) { recoverySessionData = ((SqlConnection)owningConnection)._recoverySessionData; } if (opt.ContextConnection) { result = GetContextConnection(opt, poolGroupProviderInfo); } else { bool redirectedUserInstance = false; DbConnectionPoolIdentity identity = null; // Pass DbConnectionPoolIdentity to SqlInternalConnectionTds if using integrated security. // Used by notifications. if (opt.IntegratedSecurity) { if (pool != null) { identity = pool.Identity; } else { identity = DbConnectionPoolIdentity.GetCurrent(); } } // FOLLOWING IF BLOCK IS ENTIRELY FOR SSE USER INSTANCES // If "user instance=true" is in the connection string, we're using SSE user instances if (opt.UserInstance) { // opt.DataSource is used to create the SSE connection redirectedUserInstance = true; string instanceName; if ( (null == pool) || (null != pool && pool.Count <= 0) ) { // Non-pooled or pooled and no connections in the pool. SqlInternalConnectionTds sseConnection = null; try { // What about a failure - throw? YES! // SqlConnectionString sseopt = new SqlConnectionString(opt, opt.DataSource, true /* user instance=true */, false /* set Enlist = false */); sseConnection = new SqlInternalConnectionTds(identity, sseopt, key.Credential, null, "", null, false); // NOTE: Retrieve <UserInstanceName> here. This user instance name will be used below to connect to the Sql Express User Instance. instanceName = sseConnection.InstanceName; if (!instanceName.StartsWith("\\\\.\\", StringComparison.Ordinal)) { throw SQL.NonLocalSSEInstance(); } if (null != pool) { // Pooled connection - cache result SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo) pool.ProviderInfo; // No lock since we are already in creation mutex providerInfo.InstanceName = instanceName; } } finally { if (null != sseConnection) { sseConnection.Dispose(); } } } else { // Cached info from pool. SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo) pool.ProviderInfo; // No lock since we are already in creation mutex instanceName = providerInfo.InstanceName; } // NOTE: Here connection option opt is cloned to set 'instanceName=<UserInstanceName>' that was // retrieved from the previous SSE connection. For this UserInstance connection 'Enlist=True'. // options immutable - stored in global hash - don't modify opt = new SqlConnectionString(opt, instanceName, false /* user instance=false */, null /* do not modify the Enlist value */); poolGroupProviderInfo = null; // null so we do not pass to constructor below... } result = new SqlInternalConnectionTds(identity, opt, key.Credential, poolGroupProviderInfo, "", null, redirectedUserInstance, userOpt, recoverySessionData); } return result; }
internal static SqlConnectionString FindSqlConnectionOptions(SqlConnectionPoolKey key) { SqlConnectionString connectionOptions = (SqlConnectionString )SingletonInstance.FindConnectionOptions(key); if (null == connectionOptions) { connectionOptions = new SqlConnectionString(key.ConnectionString); } if (connectionOptions.IsEmpty) { throw ADP.NoConnectionString(); } return connectionOptions; }
// although the new password is generally not used it must be passed to the c'tor // the new Login7 packet will always write out the new password (or a length of zero and no bytes if not present) // internal SqlInternalConnectionTds( DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, object providerInfo, bool redirectedUserInstance, SqlConnectionString userConnectionOptions = null, // NOTE: userConnectionOptions may be different to connectionOptions if the connection string has been expanded (see SqlConnectionString.Expand) SessionData reconnectSessionData = null, bool applyTransientFaultHandling = false) : base(connectionOptions) { #if DEBUG if (reconnectSessionData != null) { reconnectSessionData._debugReconnectDataApplied = true; } #endif Debug.Assert(reconnectSessionData == null || connectionOptions.ConnectRetryCount > 0, "Reconnect data supplied with CR turned off"); if (connectionOptions.ConnectRetryCount > 0) { _recoverySessionData = reconnectSessionData; if (reconnectSessionData == null) { _currentSessionData = new SessionData(); } else { _currentSessionData = new SessionData(_recoverySessionData); _originalDatabase = _recoverySessionData._initialDatabase; _originalLanguage = _recoverySessionData._initialLanguage; } } _identity = identity; _poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo)providerInfo; _fResetConnection = connectionOptions.ConnectionReset; if (_fResetConnection && _recoverySessionData == null) { _originalDatabase = connectionOptions.InitialCatalog; _originalLanguage = connectionOptions.CurrentLanguage; } _timeoutErrorInternal = new SqlConnectionTimeoutErrorInternal(); _parserLock.Wait(canReleaseFromAnyThread: false); ThreadHasParserLockForClose = true; // In case of error, let ourselves know that we already own the parser lock try { var timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout); // If transient fault handling is enabled then we can retry the login upto the ConnectRetryCount. int connectionEstablishCount = applyTransientFaultHandling ? connectionOptions.ConnectRetryCount + 1 : 1; int transientRetryIntervalInMilliSeconds = connectionOptions.ConnectRetryInterval * 1000; // Max value of transientRetryInterval is 60*1000 ms. The max value allowed for ConnectRetryInterval is 60 for (int i = 0; i < connectionEstablishCount; i++) { try { OpenLoginEnlist(timeout, connectionOptions, redirectedUserInstance); break; } catch (SqlException sqlex) { if (i + 1 == connectionEstablishCount || !applyTransientFaultHandling || timeout.IsExpired || timeout.MillisecondsRemaining < transientRetryIntervalInMilliSeconds || !IsTransientError(sqlex)) { throw sqlex; } else { Thread.Sleep(transientRetryIntervalInMilliSeconds); } } } } finally { ThreadHasParserLockForClose = false; _parserLock.Release(); } }
private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnectionString options) { if (serverInfo.ExtendedServerName == null) { string host = serverInfo.UserServerName; string protocol = serverInfo.UserProtocol; serverInfo.SetDerivedNames(protocol, host); } }
internal SqlInternalConnection(SqlConnectionString connectionOptions) : base() { Debug.Assert(null != connectionOptions, "null connectionOptions?"); _connectionOptions = connectionOptions; }
protected override DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous) { Debug.Assert(!ADP.IsEmpty(connectionString), "empty connectionString"); SqlConnectionString result = new SqlConnectionString(connectionString); return result; }
private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnectionString options) { if (serverInfo.ExtendedServerName == null) { string host = serverInfo.UserServerName; string protocol = serverInfo.UserProtocol; if (aliasLookup) { // We skip this for UserInstances... // Perform registry lookup to see if host is an alias. It will appropriately set host and protocol, if an Alias. // Check if it was already resolved, during CR reconnection _currentSessionData values will be copied from // _reconnectSessonData of the previous connection if (_currentSessionData != null && !string.IsNullOrEmpty(host)) { Tuple<string, string> hostPortPair; if (_currentSessionData._resolvedAliases.TryGetValue(host, out hostPortPair)) { host = hostPortPair.Item1; protocol = hostPortPair.Item2; } else { TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol); _currentSessionData._resolvedAliases.Add(serverInfo.UserServerName, new Tuple<string, string>(host, protocol)); } } else { TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol); } // if (options.EnforceLocalHost) { // verify LocalHost for |DataDirectory| usage SqlConnectionString.VerifyLocalHostAndFixup(ref host, true, true /*fix-up to "."*/); } } serverInfo.SetDerivedNames(protocol, host); } }
private SqlInternalConnectionSmi GetContextConnection(SqlConnectionString options, object providerInfo) { SmiContext smiContext = SmiContextFactory.Instance.GetCurrentContext(); SqlInternalConnectionSmi result = (SqlInternalConnectionSmi)smiContext.GetContextValue((int)SmiContextFactory.ContextKey.Connection); // context connections are automatically re-useable if they exist unless they've been doomed. if (null == result || result.IsConnectionDoomed) { if (null != result) { result.Dispose(); // A doomed connection is a messy thing. Dispose of it promptly in nearest receptacle. } result = new SqlInternalConnectionSmi(options, smiContext); smiContext.SetContextValue((int)SmiContextFactory.ContextKey.Connection, result); } result.Activate(); return result; }
// Initialize server info from connection options, internal ServerInfo(SqlConnectionString userOptions) : this(userOptions, userOptions.DataSource) {}
private void OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, string newPassword, SecureString newSecurePassword, bool redirectedUserInstance) { bool useFailoverPartner; // should we use primary or secondary first ServerInfo dataSource = new ServerInfo(connectionOptions); string failoverPartner; if (null != PoolGroupProviderInfo) { useFailoverPartner = PoolGroupProviderInfo.UseFailoverPartner; failoverPartner = PoolGroupProviderInfo.FailoverPartner; } else { // Only ChangePassword or SSE User Instance comes through this code path. useFailoverPartner = false; failoverPartner = ConnectionOptions.FailoverPartner; } timeoutErrorInternal.SetInternalSourceType(useFailoverPartner ? SqlConnectionInternalSourceType.Failover : SqlConnectionInternalSourceType.Principle); bool hasFailoverPartner = !ADP.IsEmpty(failoverPartner); // Open the connection and Login try { timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin); if (hasFailoverPartner) { timeoutErrorInternal.SetFailoverScenario(true); // this is a failover scenario LoginWithFailover( useFailoverPartner, dataSource, failoverPartner, newPassword, newSecurePassword, redirectedUserInstance, connectionOptions, credential, timeout); } else { timeoutErrorInternal.SetFailoverScenario(false); // not a failover scenario LoginNoFailover(dataSource, newPassword, newSecurePassword, redirectedUserInstance, connectionOptions, credential, timeout); } timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin); } catch (Exception e) { // if (ADP.IsCatchableExceptionType(e)) { LoginFailure(); } throw; } timeoutErrorInternal.SetAllCompleteMarker(); #if DEBUG _parser._physicalStateObj.InvalidateDebugOnlyCopyOfSniContext(); #endif }
// Initialize server info from connection options, but override DataSource with given server name internal ServerInfo (SqlConnectionString userOptions, string serverName) { //----------------- // Preconditions Debug.Assert(null != userOptions); //----------------- //Method body Debug.Assert(serverName != null, "server name should never be null"); UserServerName = (serverName ?? string.Empty); // ensure user server name is not null UserProtocol = userOptions.NetworkLibrary; ResolvedDatabaseName = userOptions.InitialCatalog; PreRoutingServerName = null; }
internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner) { if (UseFailoverPartner != actualUseFailoverPartner) { // Bid.Trace("<sc.SqlConnectionPoolGroupProviderInfo|INFO> Failover detected. failover partner='%ls'. Clearing PoolGroup\n", actualFailoverPartner); base.PoolGroup.Clear(); _useFailoverPartner = actualUseFailoverPartner; } // Only construct a new permission set when we're connecting to the // primary data source, not the failover partner. if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner) { // NOTE: we optimisitically generate the permission set to keep // lock short, but we only do this when we get a new // failover partner. // System.Security.PermissionSet failoverPermissionSet = CreateFailoverPermission(userConnectionOptions, actualFailoverPartner); lock (this) { if (_failoverPartner != actualFailoverPartner) { _failoverPartner = actualFailoverPartner; _failoverPermissionSet = failoverPermissionSet; } } } }
// Attempt to login to a host that does not have a failover partner // // Will repeatedly attempt to connect, but back off between each attempt so as not to clog the network. // Back off period increases for first few failures: 100ms, 200ms, 400ms, 800ms, then 1000ms for subsequent attempts // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // DEVNOTE: The logic in this method is paralleled by the logic in LoginWithFailover. // Changes to either one should be examined to see if they need to be reflected in the other // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! private void LoginNoFailover(ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, bool redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) { Debug.Assert(object.ReferenceEquals(connectionOptions, this.ConnectionOptions), "ConnectionOptions argument and property must be the same"); // consider removing the argument int routingAttempts = 0; ServerInfo originalServerInfo = serverInfo; // serverInfo may end up pointing to new object due to routing, original object is used to set CurrentDatasource if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, host=%ls\n", ObjectID, serverInfo.UserServerName); } int sleepInterval = 100; //milliseconds to sleep (back off) between attempts. ResolveExtendedServerName(serverInfo, !redirectedUserInstance, connectionOptions); long timeoutUnitInterval = 0; Boolean isParallel = connectionOptions.MultiSubnetFailover || connectionOptions.TransparentNetworkIPResolution; if(isParallel) { // Determine unit interval if (timeout.IsInfinite) { timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * (1000L * ADP.DefaultConnectionTimeout))); } else { timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining)); } } // Only three ways out of this loop: // 1) Successfully connected // 2) Parser threw exception while main timer was expired // 3) Parser threw logon failure-related exception // 4) Parser threw exception in post-initial connect code, // such as pre-login handshake or during actual logon. (parser state != Closed) // // Of these methods, only #1 exits normally. This preserves the call stack on the exception // back into the parser for the error cases. int attemptNumber = 0; TimeoutTimer intervalTimer = null; TimeoutTimer firstTransparentAttemptTimeout = TimeoutTimer.StartMillisecondsTimeout(ADP.FirstTransparentAttemptTimeout); TimeoutTimer attemptOneLoginTimeout = timeout; while(true) { if(isParallel) { attemptNumber++; // Set timeout for this attempt, but don't exceed original timer long nextTimeoutInterval = checked(timeoutUnitInterval * attemptNumber); long milliseconds = timeout.MillisecondsRemaining; if (nextTimeoutInterval > milliseconds) { nextTimeoutInterval = milliseconds; } intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval); } // Re-allocate parser each time to make sure state is known // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created if (_parser != null) _parser.Disconnect(); _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous); Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext)); try { // Boolean isFirstTransparentAttempt = connectionOptions.TransparentNetworkIPResolution && attemptNumber == 1; if(isFirstTransparentAttempt) { attemptOneLoginTimeout = firstTransparentAttemptTimeout; } else { if(isParallel) { attemptOneLoginTimeout = intervalTimer; } } AttemptOneLogin( serverInfo, newPassword, newSecurePassword, !isParallel, // ignore timeout for SniOpen call unless MSF , and TNIR attemptOneLoginTimeout, isFirstTransparentAttempt:isFirstTransparentAttempt); if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner) { // connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used. throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this); } if (_routingInfo != null) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover> Routed to %ls", serverInfo.ExtendedServerName); if (routingAttempts > 0) { throw SQL.ROR_RecursiveRoutingNotSupported(this); } if (timeout.IsExpired) { throw SQL.ROR_TimeoutAfterRoutingInfo(this); } serverInfo = new ServerInfo(ConnectionOptions, _routingInfo, serverInfo.ResolvedServerName); timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.RoutingDestination); _originalClientConnectionId = _clientConnectionId; _routingDestination = serverInfo.UserServerName; // restore properties that could be changed by the environment tokens _currentPacketSize = ConnectionOptions.PacketSize; _currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage; CurrentDatabase = _originalDatabase = ConnectionOptions.InitialCatalog; _currentFailoverPartner = null; _instanceName = String.Empty; routingAttempts++; continue; // repeat the loop, but skip code reserved for failed connections (after the catch) } else { break; // leave the while loop -- we've successfully connected } } catch (SqlException sqlex) { if (null == _parser || TdsParserState.Closed != _parser.State || IsDoNotRetryConnectError(sqlex) || timeout.IsExpired) { // no more time to try again throw; // Caller will call LoginFailure() } // Check sleep interval to make sure we won't exceed the timeout // Do this in the catch block so we can re-throw the current exception if (timeout.MillisecondsRemaining <= sleepInterval) { throw; } // } // We only get here when we failed to connect, but are going to re-try // Switch to failover logic if the server provided a partner if (null != ServerProvidedFailOverPartner) { if (connectionOptions.MultiSubnetFailover) { // connection failed: do not allow failover to server-provided failover partner if MultiSubnetFailover is set throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this); } Debug.Assert(ConnectionOptions.ApplicationIntent != ApplicationIntent.ReadOnly, "FAILOVER+AppIntent=RO: Should already fail (at LOGSHIPNODE in OnEnvChange)"); timeoutErrorInternal.ResetAndRestartPhase(); timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin); timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover); timeoutErrorInternal.SetFailoverScenario(true); // this is a failover scenario LoginWithFailover( true, // start by using failover partner, since we already failed to connect to the primary serverInfo, ServerProvidedFailOverPartner, newPassword, newSecurePassword, redirectedUserInstance, connectionOptions, credential, timeout); return; // LoginWithFailover successfully connected and handled entire connection setup } // Sleep for a bit to prevent clogging the network with requests, // then update sleep interval for next iteration (max 1 second interval) if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval); } Thread.Sleep(sleepInterval); sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000; } if (null != PoolGroupProviderInfo) { // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover // partner; save this information in _currentFailoverPartner. PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, ServerProvidedFailOverPartner); } CurrentDataSource = originalServerInfo.UserServerName; }
// This c-tor is used to create SSE and user instance connection strings when user instance is set to true // BUG (VSTFDevDiv) 479687: Using TransactionScope with Linq2SQL against user instances fails with "connection has been broken" message internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance) : base(connectionOptions) { _integratedSecurity = connectionOptions._integratedSecurity; _encrypt = connectionOptions._encrypt; _mars = connectionOptions._mars; _persistSecurityInfo = connectionOptions._persistSecurityInfo; _pooling = connectionOptions._pooling; _replication = connectionOptions._replication; _userInstance = userInstance; _connectTimeout = connectionOptions._connectTimeout; _loadBalanceTimeout = connectionOptions._loadBalanceTimeout; _maxPoolSize = connectionOptions._maxPoolSize; _minPoolSize = connectionOptions._minPoolSize; _multiSubnetFailover = connectionOptions._multiSubnetFailover; _packetSize = connectionOptions._packetSize; _applicationName = connectionOptions._applicationName; _attachDBFileName = connectionOptions._attachDBFileName; _currentLanguage = connectionOptions._currentLanguage; _dataSource = dataSource; _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource); _failoverPartner = connectionOptions._failoverPartner; _initialCatalog = connectionOptions._initialCatalog; _password = connectionOptions._password; _userID = connectionOptions._userID; _workstationId = connectionOptions._workstationId; _typeSystemVersion = connectionOptions._typeSystemVersion; _applicationIntent = connectionOptions._applicationIntent; _connectRetryCount = connectionOptions._connectRetryCount; _connectRetryInterval = connectionOptions._connectRetryInterval; ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source); }
// Attempt to login to a host that has a failover partner // // Connection & timeout sequence is // First target, timeout = interval * 1 // second target, timeout = interval * 1 // sleep for 100ms // First target, timeout = interval * 2 // Second target, timeout = interval * 2 // sleep for 200ms // First Target, timeout = interval * 3 // etc. // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // DEVNOTE: The logic in this method is paralleled by the logic in LoginNoFailover. // Changes to either one should be examined to see if they need to be reflected in the other // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! private void LoginWithFailover( bool useFailoverHost, ServerInfo primaryServerInfo, string failoverHost, string newPassword, SecureString newSecurePassword, bool redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout ) { Debug.Assert(!connectionOptions.MultiSubnetFailover, "MultiSubnetFailover should not be set if failover partner is used"); if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", ObjectID, useFailoverHost); Bid.PutStr(primaryServerInfo.UserServerName); Bid.PutStr(", failover="); Bid.PutStr(failoverHost); Bid.PutStr("\n"); } int sleepInterval = 100; //milliseconds to sleep (back off) between attempts. long timeoutUnitInterval; string protocol = ConnectionOptions.NetworkLibrary; ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost); ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions); if (null == ServerProvidedFailOverPartner) {// No point in resolving the failover partner when we're going to override it below // Don't resolve aliases if failover == primary // ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions); } // Determine unit interval if (timeout.IsInfinite) { timeoutUnitInterval = checked((long) ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout)); } else { timeoutUnitInterval = checked((long) (ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining)); } // Initialize loop variables bool failoverDemandDone = false; // have we demanded for partner information yet (as necessary)? int attemptNumber = 0; // Only three ways out of this loop: // 1) Successfully connected // 2) Parser threw exception while main timer was expired // 3) Parser threw logon failure-related exception (LOGON_FAILED, PASSWORD_EXPIRED, etc) // // Of these methods, only #1 exits normally. This preserves the call stack on the exception // back into the parser for the error cases. while (true) { // Set timeout for this attempt, but don't exceed original timer long nextTimeoutInterval = checked(timeoutUnitInterval * ((attemptNumber / 2) + 1)); long milliseconds = timeout.MillisecondsRemaining; if (nextTimeoutInterval > milliseconds) { nextTimeoutInterval = milliseconds; } TimeoutTimer intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval); // Re-allocate parser each time to make sure state is known // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created if (_parser != null) _parser.Disconnect(); _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous); Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext)); ServerInfo currentServerInfo; if (useFailoverHost) { if (!failoverDemandDone) { FailoverPermissionDemand(); failoverDemandDone = true; } // Primary server may give us a different failover partner than the connection string indicates. Update it if (null != ServerProvidedFailOverPartner && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner) { if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", ObjectID, ServerProvidedFailOverPartner); } failoverServerInfo.SetDerivedNames(protocol, ServerProvidedFailOverPartner); } currentServerInfo = failoverServerInfo; timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover); } else { currentServerInfo = primaryServerInfo; timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Principle); } try { // Attempt login. Use timerInterval for attempt timeout unless infinite timeout was requested. AttemptOneLogin( currentServerInfo, newPassword, newSecurePassword, false, // Use timeout in SniOpen intervalTimer, withFailover:true ); if (_routingInfo != null) { // We are in login with failover scenation and server sent routing information // If it is read-only routing - we did not supply AppIntent=RO (it should be checked before) // If it is something else, not known yet (future server) - this client is not designed to support this. // In any case, server should not have sent the routing info. Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", _routingInfo.ServerName); throw SQL.ROR_UnexpectedRoutingInfo(this); } break; // leave the while loop -- we've successfully connected } catch (SqlException sqlex) { if (IsDoNotRetryConnectError(sqlex) || timeout.IsExpired) { // no more time to try again throw; // Caller will call LoginFailure() } if (IsConnectionDoomed) { throw; } if (1 == attemptNumber % 2) { // Check sleep interval to make sure we won't exceed the original timeout // Do this in the catch block so we can re-throw the current exception if (timeout.MillisecondsRemaining <= sleepInterval) { throw; } } // } // We only get here when we failed to connect, but are going to re-try // After trying to connect to both servers fails, sleep for a bit to prevent clogging // the network with requests, then update sleep interval for next iteration (max 1 second interval) if (1 == attemptNumber % 2) { if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval); } Thread.Sleep(sleepInterval); sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000; } // Update attempt number and target host attemptNumber++; useFailoverHost = !useFailoverHost; } // If we get here, connection/login succeeded! Just a few more checks & record-keeping // if connected to failover host, but said host doesn't have DbMirroring set up, throw an error if (useFailoverHost && null == ServerProvidedFailOverPartner) { throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase); } if (null != PoolGroupProviderInfo) { // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover // partner; save this information in _currentFailoverPartner. PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner); } CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName); }