protected override DbConnectionInternal CreateConnection(DbConnectionOptions options, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) { return new OleDbConnectionInternal((OleDbConnectionString) options, (OleDbConnection) owningObject); }
abstract protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection);
override protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) { return CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningConnection, userOptions: null); }
internal void MakePooledConnection(DbConnectionPool connectionPool) { // Used by DbConnectionFactory to indicate that this object IS part of // a connection pool. // _createTime = DateTime.UtcNow; // WebData 111116 _connectionPool = connectionPool; _performanceCounters = connectionPool.PerformanceCounters; }
internal DbConnectionInternal CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions) { Debug.Assert(null != pool, "null pool?"); DbConnectionPoolGroupProviderInfo poolGroupProviderInfo = pool.PoolGroup.ProviderInfo; DbConnectionInternal newConnection = CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningObject, userOptions); if (null != newConnection) { newConnection.MakePooledConnection(pool); } return newConnection; }
internal void MakePooledConnection(DbConnectionPool connectionPool) { // Used by DbConnectionFactory to indicate that this object IS part of // a connection pool. _createTime = DateTime.UtcNow; _connectionPool = connectionPool; }
public virtual void Dispose() { _connectionPool = null; _performanceCounters = null; _connectionIsDoomed = true; _enlistedTransactionOriginal = null; // should not be disposed // Dispose of the _enlistedTransaction since it is a clone // of the original reference. // VSDD 780271 - _enlistedTransaction can be changed by another thread (TX end event) SysTx.Transaction enlistedTransaction = Interlocked.Exchange(ref _enlistedTransaction, null); if (enlistedTransaction != null) { enlistedTransaction.Dispose(); } }
internal bool Prune() { // must only call from DbConnectionFactory.PruneConnectionPoolGroups on background timer thread // must lock(DbConnectionFactory._connectionPoolGroups.SyncRoot) before calling ReadyToRemove // to avoid conflict with DbConnectionFactory.CreateConnectionPoolGroup replacing pool entry lock (this) { if (_poolCollection.Count > 0) { var newPoolCollection = new ConcurrentDictionary <DbConnectionPoolIdentity, DbConnectionPool>(); foreach (var entry in _poolCollection) { DbConnectionPool pool = entry.Value; if (pool != null) { // Pruning a pool while a connection is currently attempting to connect // will cause the pool to be prematurely abandoned. The only known effect so // far is that the errorWait throttling will be reset when this occurs. // We should be able to avoid this situation by not pruning the pool if // it's _waitCount is non-zero (i.e. no connections *in* the pool, but also // no connections attempting to be created for the pool). // Actually prune the pool if there are no connections in the pool and no errors occurred. // Empty pool during pruning indicates zero or low activity, but // an error state indicates the pool needs to stay around to // throttle new connection attempts. if ((!pool.ErrorOccurred) && (0 == pool.Count)) { // Order is important here. First we remove the pool // from the collection of pools so no one will try // to use it while we're processing and finally we put the // pool into a list of pools to be released when they // are completely empty. DbConnectionFactory connectionFactory = pool.ConnectionFactory; connectionFactory.PerformanceCounters.NumberOfActiveConnectionPools.Decrement(); connectionFactory.QueuePoolForRelease(pool, false); } else { newPoolCollection.TryAdd(entry.Key, entry.Value); } } } _poolCollection = newPoolCollection; } // must be pruning thread to change state and no connections // otherwise pruning thread risks making entry disabled soon after user calls ClearPool if (0 == _poolCollection.Count) { if (PoolGroupStateActive == _state) { _state = PoolGroupStateIdle; } else if (PoolGroupStateIdle == _state) { _state = PoolGroupStateDisabled; } } return(PoolGroupStateDisabled == _state); } }
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); }
internal virtual void CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory) { // The implementation here is the implementation required for the // "open" internal connections, since our own private "closed" // singleton internal connection objects override this method to // prevent anything funny from happening (like disposing themselves // or putting them into a connection pool) // // Derived class should override DbConnectionInternal.Deactivate and DbConnectionInternal.Dispose // for cleaning up after DbConnection.Close // protected override void Deactivate() { // override DbConnectionInternal.Close // // do derived class connection deactivation for both pooled & non-pooled connections // } // public override void Dispose() { // override DbConnectionInternal.Close // // do derived class cleanup // base.Dispose(); // } // // overriding DbConnection.Close is also possible, but must provider for their own synchronization // public override void Close() { // override DbConnection.Close // base.Close(); // // do derived class outer connection for both pooled & non-pooled connections // // user must do their own synchronization here // } // // if the DbConnectionInternal derived class needs to close the connection it should // delegate to the DbConnection if one exists or directly call dispose // DbConnection owningObject = (DbConnection)Owner; // if (null != owningObject) { // owningObject.Close(); // force the closed state on the outer object. // } // else { // Dispose(); // } // //////////////////////////////////////////////////////////////// // DON'T MESS WITH THIS CODE UNLESS YOU KNOW WHAT YOU'RE DOING! //////////////////////////////////////////////////////////////// Debug.Assert(null != owningObject, "null owningObject"); Debug.Assert(null != connectionFactory, "null connectionFactory"); // if an exception occurs after the state change but before the try block // the connection will be stuck in OpenBusy state. The commented out try-catch // block doesn't really help because a ThreadAbort during the finally block // would just revert the connection to a bad state. // Open->Closed: guarantee internal connection is returned to correct pool if (connectionFactory.SetInnerConnectionFrom(owningObject, DbConnectionOpenBusy.SingletonInstance, this)) { // Lock to prevent race condition with cancellation lock (this) { object lockToken = ObtainAdditionalLocksForClose(); try { PrepareForCloseConnection(); DbConnectionPool connectionPool = Pool; // The singleton closed classes won't have owners and // connection pools, and we won't want to put them back // into the pool. if (null != connectionPool) { connectionPool.PutObject(this, owningObject); // PutObject calls Deactivate for us... // NOTE: Before we leave the PutObject call, another // thread may have already popped the connection from // the pool, so don't expect to be able to verify it. } else { Deactivate(); // ensure we de-activate non-pooled connections, or the data readers and transactions may not get cleaned up... // To prevent an endless recursion, we need to clear // the owning object before we call dispose so that // we can't get here a second time... Ordinarily, I // would call setting the owner to null a hack, but // this is safe since we're about to dispose the // object and it won't have an owner after that for // certain. _owningObject.Target = null; Dispose(); } } finally { ReleaseAdditionalLocksForClose(lockToken); // if a ThreadAbort puts us here then its possible the outer connection will not reference // this and this will be orphaned, not reclaimed by object pool until outer connection goes out of scope. connectionFactory.SetInnerConnectionEvent(owningObject, DbConnectionClosedPreviouslyOpened.SingletonInstance); } } } }
internal DbConnectionPool?GetConnectionPool(DbConnectionFactory connectionFactory) { // When this method returns null it indicates that the connection // factory should not use pooling. // We don't support connection pooling on Win9x; it lacks too // many of the APIs we require. // PoolGroupOptions will only be null when we're not supposed to pool // connections. DbConnectionPool?pool = null; if (null != _poolGroupOptions) { Debug.Assert(ADP.IsWindowsNT, "should not be pooling on Win9x"); DbConnectionPoolIdentity?currentIdentity = DbConnectionPoolIdentity.NoIdentity; if (_poolGroupOptions.PoolByIdentity) { // if we're pooling by identity (because integrated security is // being used for these connections) then we need to go out and // search for the connectionPool that matches the current identity. currentIdentity = DbConnectionPoolIdentity.GetCurrent(); // If the current token is restricted in some way, then we must // not attempt to pool these connections. if (currentIdentity.IsRestricted) { currentIdentity = null; } } if (null != currentIdentity) { if (!_poolCollection.TryGetValue(currentIdentity, out pool)) { // find the pool lock (this) { // Did someone already add it to the list? if (!_poolCollection.TryGetValue(currentIdentity, out pool)) { DbConnectionPool newPool = new DbConnectionPool(connectionFactory, this, currentIdentity); if (MarkPoolGroupAsActive()) { // If we get here, we know for certain that we there isn't // a pool that matches the current identity, so we have to // add the optimistically created one newPool.Startup(); // must start pool before usage bool addResult = _poolCollection.TryAdd(currentIdentity, newPool); Debug.Assert(addResult, "No other pool with current identity should exist at this point"); connectionFactory.PerformanceCounters.NumberOfActiveConnectionPools.Increment(); pool = newPool; } else { // else pool entry has been disabled so don't create new pools Debug.Assert(PoolGroupStateDisabled == _state, "state should be disabled"); // don't need to call connectionFactory.QueuePoolForRelease(newPool) because // pool callbacks were delayed and no risk of connections being created newPool.Shutdown(); } } else { // else found an existing pool to use instead Debug.Assert(PoolGroupStateActive == _state, "state should be active since a pool exists and lock holds"); } } } // the found pool could be in any state } } if (null == pool) { lock (this) { // keep the pool entry state active when not pooling MarkPoolGroupAsActive(); } } return(pool); }
virtual protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) { return(CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningConnection)); }
internal void QueuePoolForRelease(DbConnectionPool pool, bool clearing) { pool.Shutdown(); lock (this._poolsToRelease) { if (clearing) { pool.Clear(); } this._poolsToRelease.Add(pool); } this.PerformanceCounters.NumberOfInactiveConnectionPools.Increment(); }
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; }
internal DbConnectionPool GetConnectionPool(DbConnectionFactory connectionFactory) { // When this method returns null it indicates that the connection // factory should not use pooling. // We don't support connection pooling on Win9x; it lacks too // many of the APIs we require. // PoolGroupOptions will only be null when we're not supposed to pool // connections. DbConnectionPool pool = null; if (null != _poolGroupOptions) { Debug.Assert(ADP.IsWindowsNT, "should not be pooling on Win9x"); DbConnectionPoolIdentity currentIdentity = DbConnectionPoolIdentity.NoIdentity; if (_poolGroupOptions.PoolByIdentity) { // if we're pooling by identity (because integrated security is // being used for these connections) then we need to go out and // search for the connectionPool that matches the current identity. currentIdentity = DbConnectionPoolIdentity.GetCurrent(); // If the current token is restricted in some way, then we must // not attempt to pool these connections. if (currentIdentity.IsRestricted) { currentIdentity = null; } } if (null != currentIdentity) { if (!_poolCollection.TryGetValue(currentIdentity, out pool)) { // find the pool DbConnectionPoolProviderInfo connectionPoolProviderInfo = connectionFactory.CreateConnectionPoolProviderInfo(this.ConnectionOptions); // optimistically create pool, but its callbacks are delayed until after actual add DbConnectionPool newPool = new DbConnectionPool(connectionFactory, this, currentIdentity, connectionPoolProviderInfo); lock (this) { // Did someone already add it to the list? if (!_poolCollection.TryGetValue(currentIdentity, out pool)) { if (MarkPoolGroupAsActive()) { // If we get here, we know for certain that we there isn't // a pool that matches the current identity, so we have to // add the optimistically created one newPool.Startup(); // must start pool before usage bool addResult = _poolCollection.TryAdd(currentIdentity, newPool); Debug.Assert(addResult, "No other pool with current identity should exist at this point"); #if !MOBILE connectionFactory.PerformanceCounters.NumberOfActiveConnectionPools.Increment(); #endif pool = newPool; newPool = null; } else { // else pool entry has been disabled so don't create new pools Debug.Assert(PoolGroupStateDisabled == _state, "state should be disabled"); } } else { // else found an existing pool to use instead Debug.Assert(PoolGroupStateActive == _state, "state should be active since a pool exists and lock holds"); } } if (null != newPool) { // don't need to call connectionFactory.QueuePoolForRelease(newPool) because // pool callbacks were delayed and no risk of connections being created newPool.Shutdown(); } } // the found pool could be in any state } } if (null == pool) { lock(this) { // keep the pool entry state active when not pooling MarkPoolGroupAsActive(); } } return pool; }
protected abstract DbConnectionInternal CreateConnection(DbConnectionOptions options, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection);
public virtual void Dispose() { _connectionPool = null; _connectionIsDoomed = true; }
internal DbConnectionPool GetConnectionPool(DbConnectionFactory connectionFactory) { object obj2 = null; if (this._poolGroupOptions != null) { DbConnectionPoolIdentity noIdentity = DbConnectionPoolIdentity.NoIdentity; if (this._poolGroupOptions.PoolByIdentity) { noIdentity = DbConnectionPoolIdentity.GetCurrent(); if (noIdentity.IsRestricted) { noIdentity = null; } } if (noIdentity != null) { obj2 = this._poolCollection[noIdentity]; if (obj2 == null) { DbConnectionPoolProviderInfo connectionPoolProviderInfo = connectionFactory.CreateConnectionPoolProviderInfo(this.ConnectionOptions); DbConnectionPool pool = new DbConnectionPool(connectionFactory, this, noIdentity, connectionPoolProviderInfo); lock (this) { HybridDictionary dictionary = this._poolCollection; obj2 = dictionary[noIdentity]; if ((obj2 == null) && this.MarkPoolGroupAsActive()) { pool.Startup(); HybridDictionary dictionary2 = new HybridDictionary(1 + dictionary.Count, false); foreach (DictionaryEntry entry in dictionary) { dictionary2.Add(entry.Key, entry.Value); } dictionary2.Add(noIdentity, pool); connectionFactory.PerformanceCounters.NumberOfActiveConnectionPools.Increment(); this._poolCollection = dictionary2; this._poolCount = dictionary2.Count; obj2 = pool; pool = null; } } if (pool != null) { pool.Shutdown(); } } } } if (obj2 == null) { lock (this) { this.MarkPoolGroupAsActive(); } } return (DbConnectionPool) obj2; }
protected override System.Data.ProviderBase.DbConnectionInternal CreateConnection(System.Data.Common.DbConnectionOptions options, object poolGroupProviderInfo, System.Data.ProviderBase.DbConnectionPool pool, DbConnection owningObject) { return(new OracleInternalConnection(options as OracleConnectionString)); }
override protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) { DbConnectionInternal result = new OleDbConnectionInternal((OleDbConnectionString)options, (OleDbConnection)owningObject); return result; }
internal void MakeNonPooledObject(object owningObject, DbConnectionPoolCounters performanceCounters) { // Used by DbConnectionFactory to indicate that this object IS NOT part of // a connection pool. _connectionPool = null; _performanceCounters = performanceCounters; _owningObject.Target = owningObject; _pooledCount = -1; }
internal DbConnectionInternal CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions) { Debug.Assert(null != pool, "null pool?"); DbConnectionPoolGroupProviderInfo poolGroupProviderInfo = pool.PoolGroup.ProviderInfo; DbConnectionInternal newConnection = CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningObject, userOptions); if (null != newConnection) { PerformanceCounters.HardConnectsPerSecond.Increment(); newConnection.MakePooledConnection(pool); } Bid.Trace("<prov.DbConnectionFactory.CreatePooledConnection|RES|CPOOL> %d#, Pooled database connection created.\n", ObjectID); return newConnection; }
override protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) { DbConnectionInternal result = new OdbcConnectionOpen(owningObject as OdbcConnection, options as OdbcConnectionString); return result; }
public virtual void Dispose() { this._connectionPool = null; this._performanceCounters = null; this._connectionIsDoomed = true; this._enlistedTransactionOriginal = null; Transaction transaction = Interlocked.Exchange<Transaction>(ref this._enlistedTransaction, null); if (transaction != null) { transaction.Dispose(); } }
internal void QueuePoolForRelease(DbConnectionPool pool, bool clearing) { // Queue the pool up for release -- we'll clear it out and dispose // of it as the last part of the pruning timer callback so we don't // do it with the pool entry or the pool collection locked. Debug.Assert(null != pool, "null pool?"); // set the pool to the shutdown state to force all active // connections to be automatically disposed when they // are returned to the pool pool.Shutdown(); lock (_poolsToRelease) { if (clearing) { pool.Clear(); } _poolsToRelease.Add(pool); } }
internal void MakeNonPooledObject(object owningObject, DbConnectionPoolCounters performanceCounters) { this._connectionPool = null; this._performanceCounters = performanceCounters; this._owningObject.Target = owningObject; this._pooledCount = -1; }
// 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); } }
internal void MakePooledConnection(DbConnectionPool connectionPool) { this._createTime = DateTime.UtcNow; this._connectionPool = connectionPool; this._performanceCounters = connectionPool.PerformanceCounters; }
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; }
protected override DbConnectionInternal CreateConnection(DbConnectionOptions options, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) { return new OdbcConnectionOpen(owningObject as OdbcConnection, options as OdbcConnectionString); }