diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs index 8eaaa51c12..64ec615d89 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs @@ -1326,11 +1326,6 @@ private void CreateOrValidateConnection(string method) throw ADP.ConnectionRequired(method); } - if (_connection.IsContextConnection) - { - throw SQL.NotAvailableOnContextConnection(); - } - if (_ownConnection && _connection.State != ConnectionState.Open) { _connection.Open(); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs index 5bc7eed53a..7219e5a8db 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -1072,29 +1072,18 @@ public override void Prepare() // between entry into Execute* API and the thread obtaining the stateObject. _pendingCancel = false; - // Context connection's prepare is a no-op - if (_activeConnection != null && _activeConnection.IsContextConnection) - { - return; - } - - SqlStatistics statistics = null; using (TryEventScope.Create(" {0}", ObjectID)) { SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current); - statistics = SqlStatistics.StartTimer(Statistics); + SqlStatistics statistics = SqlStatistics.StartTimer(Statistics); // only prepare if batch with parameters // MDAC BUG #'s 73776 & 72101 if ( - this.IsPrepared && !this.IsDirty - || (this.CommandType == CommandType.StoredProcedure) - || ( - (System.Data.CommandType.Text == this.CommandType) - && (0 == GetParameterCount(_parameters)) - ) - + IsPrepared && !IsDirty + || CommandType == CommandType.StoredProcedure + || (CommandType == CommandType.Text && GetParameterCount(_parameters) == 0) ) { if (Statistics != null) @@ -1203,12 +1192,6 @@ private void InternalPrepare() // SqlInternalConnectionTds needs to be able to unprepare a statement internal void Unprepare() { - // Context connection's prepare is a no-op - if (_activeConnection.IsContextConnection) - { - return; - } - Debug.Assert(true == IsPrepared, "Invalid attempt to Unprepare a non-prepared command!"); Debug.Assert(_activeConnection != null, "must have an open connection to UnPrepare"); Debug.Assert(false == _inPrepare, "_inPrepare should be false!"); @@ -2041,25 +2024,14 @@ private Task InternalExecuteNonQuery(TaskCompletionSource completion, st Task task = null; - // only send over SQL Batch command if we are not a stored proc and have no parameters and not in batch RPC mode - if (_activeConnection.IsContextConnection) - { - if (statistics != null) - { - statistics.SafeIncrement(ref statistics._unpreparedExecs); - } - - RunExecuteNonQuerySmi(sendToPipe); - } - //Always Encrypted generally operates only on parameterized queries. However enclave based Always encrypted also supports unparameterized queries //We skip this block for enclave based always encrypted so that we can make a call to SQL Server to get the encryption information - else if (!ShouldUseEnclaveBasedWorkflow && !_batchRPCMode && (System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters))) + if (!ShouldUseEnclaveBasedWorkflow && !_batchRPCMode && CommandType == CommandType.Text && GetParameterCount(_parameters) == 0) { Debug.Assert(!sendToPipe, "trying to send non-context command to pipe"); if (statistics != null) { - if (!this.IsDirty && this.IsPrepared) + if (!IsDirty && IsPrepared) { statistics.SafeIncrement(ref statistics._preparedExecs); } @@ -4045,83 +4017,6 @@ private Task RunExecuteNonQueryTds(string methodName, bool async, int timeout, b return null; } - // Smi-specific logic for ExecuteNonQuery - private void RunExecuteNonQuerySmi(bool sendToPipe) - { - SqlInternalConnectionSmi innerConnection = InternalSmiConnection; - - // Set it up, process all of the events, and we're done! - SmiRequestExecutor requestExecutor = null; - try - { - requestExecutor = SetUpSmiRequest(innerConnection); - SmiExecuteType execType; - if (sendToPipe) - execType = SmiExecuteType.ToPipe; - else - execType = SmiExecuteType.NonQuery; - - - SmiEventStream eventStream = null; - // Don't need a CER here because caller already has one that will doom the - // connection if it's a finally-skipping type of problem. - bool processFinallyBlock = true; - try - { - long transactionId; - Transaction transaction; - innerConnection.GetCurrentTransactionPair(out transactionId, out transaction); - - SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, innerConnection={1}, transactionId=0x{2}, cmdBehavior={3}.", ObjectID, innerConnection.ObjectID, transactionId, (int)CommandBehavior.Default); - - if (SmiContextFactory.Instance.NegotiatedSmiVersion >= SmiContextFactory.Sql2008Version) - { - eventStream = requestExecutor.Execute( - innerConnection.SmiConnection, - transactionId, - transaction, - CommandBehavior.Default, - execType); - } - else - { - eventStream = requestExecutor.Execute( - innerConnection.SmiConnection, - transactionId, - CommandBehavior.Default, - execType); - } - - while (eventStream.HasEvents) - { - eventStream.ProcessEvent(EventSink); - } - } - catch (Exception e) - { - processFinallyBlock = ADP.IsCatchableExceptionType(e); - throw; - } - finally - { - if (eventStream != null && processFinallyBlock) - { - eventStream.Close(EventSink); - } - } - - EventSink.ProcessMessagesAndThrow(); - } - finally - { - if (requestExecutor != null) - { - requestExecutor.Close(EventSink); - EventSink.ProcessMessagesAndThrow(ignoreNonFatalMessages: true); - } - } - } - /// /// Resets the encryption related state of the command object and each of the parameters. /// BatchRPC doesn't need special handling to cleanup the state of each RPC object and its parameters since a new RPC object and @@ -5160,11 +5055,7 @@ internal SqlDataReader RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior // Reset the encryption related state of the command and its parameters. ResetEncryptionState(); - if (_activeConnection.IsContextConnection) - { - return RunExecuteReaderSmi(cmdBehavior, runBehavior, returnStream); - } - else if (IsColumnEncryptionEnabled) + if (IsColumnEncryptionEnabled) { Task returnTask = null; PrepareForTransparentEncryption(cmdBehavior, returnStream, async, timeout, completion, out returnTask, asyncWrite && async, out usedCache, inRetry); @@ -5635,89 +5526,6 @@ private SqlDataReader RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavi return ds; } - private SqlDataReader RunExecuteReaderSmi(CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream) - { - SqlInternalConnectionSmi innerConnection = InternalSmiConnection; - - SmiEventStream eventStream = null; - SqlDataReader ds = null; - SmiRequestExecutor requestExecutor = null; - try - { - // Set it up, process all of the events, and we're done! - requestExecutor = SetUpSmiRequest(innerConnection); - - long transactionId; - Transaction transaction; - innerConnection.GetCurrentTransactionPair(out transactionId, out transaction); - SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, innerConnection={1}, transactionId=0x{2}, commandBehavior={(int)cmdBehavior}.", ObjectID, innerConnection.ObjectID, transactionId); - - if (SmiContextFactory.Instance.NegotiatedSmiVersion >= SmiContextFactory.Sql2008Version) - { - eventStream = requestExecutor.Execute( - innerConnection.SmiConnection, - transactionId, - transaction, - cmdBehavior, - SmiExecuteType.Reader - ); - } - else - { - eventStream = requestExecutor.Execute( - innerConnection.SmiConnection, - transactionId, - cmdBehavior, - SmiExecuteType.Reader - ); - } - - if ((runBehavior & RunBehavior.UntilDone) != 0) - { - - // Consume the results - while (eventStream.HasEvents) - { - eventStream.ProcessEvent(EventSink); - } - eventStream.Close(EventSink); - } - - if (returnStream) - { - ds = new SqlDataReaderSmi(eventStream, this, cmdBehavior, innerConnection, EventSink, requestExecutor); - ds.NextResult(); // Position on first set of results - _activeConnection.AddWeakReference(ds, SqlReferenceCollection.DataReaderTag); - } - - EventSink.ProcessMessagesAndThrow(); - } - catch (Exception e) - { - // VSTS 159716 - we do not want to handle ThreadAbort, OutOfMemory or similar critical exceptions - // because the state of used objects might remain invalid in this case - if (!ADP.IsCatchableOrSecurityExceptionType(e)) - { - throw; - } - - if (eventStream != null) - { - eventStream.Close(EventSink); // UNDONE: should cancel instead! - } - - if (requestExecutor != null) - { - requestExecutor.Close(EventSink); - EventSink.ProcessMessagesAndThrow(ignoreNonFatalMessages: true); - } - - throw; - } - - return ds; - } - private SqlDataReader CompleteAsyncExecuteReader(bool isInternal = false, bool forDescribeParameterEncryption = false) { SqlDataReader ds = cachedAsyncState.CachedAsyncReader; // should not be null @@ -5985,12 +5793,6 @@ private void ValidateCommand(string method, bool async) { throw ADP.CommandTextRequired(method); } - - if ((async) && (_activeConnection.IsContextConnection)) - { - // Async not supported on Context Connections - throw SQL.NotAvailableOnContextConnection(); - } } private void ValidateAsyncCommand() @@ -7424,190 +7226,6 @@ internal SqlException GetErrors(int commandIndex) return result; } - // Allocates and initializes a new SmiRequestExecutor based on the current command state - private SmiRequestExecutor SetUpSmiRequest(SqlInternalConnectionSmi innerConnection) - { - - // General Approach To Ensure Security of Marshalling: - // Only touch each item in the command once - // (i.e. only grab a reference to each param once, only - // read the type from that param once, etc.). The problem is - // that if the user changes something on the command in the - // middle of marshaling, it can overwrite the native buffers - // set up. For example, if max length is used to allocate - // buffers, but then re-read from the parameter to truncate - // strings, the user could extend the length and overwrite - // the buffer. - - if (Notification != null) - { - throw SQL.NotificationsNotAvailableOnContextConnection(); - } - - SmiParameterMetaData[] requestMetaData = null; - ParameterPeekAheadValue[] peekAheadValues = null; - - // Length of rgMetadata becomes *the* official count of parameters to use, - // don't rely on Parameters.Count after this point, as the user could change it. - int count = GetParameterCount(Parameters); - if (0 < count) - { - requestMetaData = new SmiParameterMetaData[count]; - peekAheadValues = new ParameterPeekAheadValue[count]; - - // set up the metadata - for (int index = 0; index < count; index++) - { - SqlParameter param = Parameters[index]; - param.Validate(index, CommandType.StoredProcedure == CommandType); - requestMetaData[index] = param.MetaDataForSmi(out peekAheadValues[index]); - - // Check for valid type for version negotiated - if (!innerConnection.Is2008OrNewer) - { - MetaType mt = MetaType.GetMetaTypeFromSqlDbType(requestMetaData[index].SqlDbType, requestMetaData[index].IsMultiValued); - if (!mt.Is90Supported) - { - throw ADP.VersionDoesNotSupportDataType(mt.TypeName); - } - } - } - } - - // Allocate the new request - CommandType cmdType = CommandType; - _smiRequestContext = innerConnection.InternalContext; - SmiRequestExecutor requestExecutor = _smiRequestContext.CreateRequestExecutor( - CommandText, - cmdType, - requestMetaData, - EventSink - ); - - // deal with errors - EventSink.ProcessMessagesAndThrow(); - - // Now assign param values - for (int index = 0; index < count; index++) - { - if (ParameterDirection.Output != requestMetaData[index].Direction && - ParameterDirection.ReturnValue != requestMetaData[index].Direction) - { - SqlParameter param = Parameters[index]; - // going back to command for parameter is ok, since we'll only pick up values now. - object value = param.GetCoercedValue(); - if (value is XmlDataFeed && requestMetaData[index].SqlDbType != SqlDbType.Xml) - { - value = MetaType.GetStringFromXml(((XmlDataFeed)value)._source); - } - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(requestMetaData[index].SqlDbType, requestMetaData[index].IsMultiValued, value, null /* parameters don't use CLR Type for UDTs */, SmiContextFactory.Instance.NegotiatedSmiVersion); - - // Handle null reference as special case for parameters - if (CommandType.StoredProcedure == cmdType && - ExtendedClrTypeCode.Empty == typeCode) - { - requestExecutor.SetDefault(index); - } - else - { - // SQLBU 402391 & 403631: Exception to prevent Parameter.Size data corruption cases from working. - // This should be temporary until changing to correct behavior can be safely implemented. - // initial size criteria is the same for all affected types - // NOTE: assumes size < -1 is handled by SqlParameter.Size setter - int size = param.Size; - if (size != 0 && size != SmiMetaData.UnlimitedMaxLengthIndicator && !param.SizeInferred) - { - switch (requestMetaData[index].SqlDbType) - { - case SqlDbType.Image: - case SqlDbType.Text: - if (size != Int32.MaxValue) - { - throw SQL.ParameterSizeRestrictionFailure(index); - } - break; - - case SqlDbType.NText: - if (size != Int32.MaxValue / 2) - { - throw SQL.ParameterSizeRestrictionFailure(index); - } - break; - - case SqlDbType.VarBinary: - case SqlDbType.VarChar: - // Allow size==Int32.MaxValue because of DeriveParameters - if (size > 0 && size != Int32.MaxValue && requestMetaData[index].MaxLength == SmiMetaData.UnlimitedMaxLengthIndicator) - { - throw SQL.ParameterSizeRestrictionFailure(index); - } - break; - - case SqlDbType.NVarChar: - // Allow size==Int32.MaxValue/2 because of DeriveParameters - if (size > 0 && size != Int32.MaxValue / 2 && requestMetaData[index].MaxLength == SmiMetaData.UnlimitedMaxLengthIndicator) - { - throw SQL.ParameterSizeRestrictionFailure(index); - } - break; - - case SqlDbType.Timestamp: - // Size limiting for larger values will happen due to MaxLength - if (size < SmiMetaData.DefaultTimestamp.MaxLength) - { - throw SQL.ParameterSizeRestrictionFailure(index); - } - break; - - case SqlDbType.Variant: - // Variant problems happen when Size is less than maximums for character and binary values - // Size limiting for larger values will happen due to MaxLength - // NOTE: assumes xml and udt types are handled in parameter value coercion - // since server does not allow these types in a variant - if (value != null) - { - MetaType mt = MetaType.GetMetaTypeFromValue(value); - - if ((mt.IsNCharType && size < SmiMetaData.MaxUnicodeCharacters) || - (mt.IsBinType && size < SmiMetaData.MaxBinaryLength) || - (mt.IsAnsiType && size < SmiMetaData.MaxANSICharacters)) - { - throw SQL.ParameterSizeRestrictionFailure(index); - } - } - break; - - case SqlDbType.Xml: - // Xml is an issue for non-SqlXml types - if (value != null && ExtendedClrTypeCode.SqlXml != typeCode) - { - throw SQL.ParameterSizeRestrictionFailure(index); - } - break; - - // NOTE: Char, NChar, Binary and UDT do not need restricting because they are always 8k or less, - // so the metadata MaxLength will match the Size setting. - - default: - break; - } - } - - if (innerConnection.Is2008OrNewer) - { - ValueUtilsSmi.SetCompatibleValueV200(EventSink, requestExecutor, index, requestMetaData[index], value, typeCode, param.Offset, peekAheadValues[index]); - } - else - { - ValueUtilsSmi.SetCompatibleValue(EventSink, requestExecutor, index, requestMetaData[index], value, typeCode, param.Offset); - } - } - } - } - - return requestExecutor; - } - private void WriteBeginExecuteEvent() { SqlClientEventSource.Log.TryBeginExecuteEvent(ObjectID, Connection?.DataSource, Connection?.Database, CommandText, Connection?.ClientConnectionId); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs index 04fa51992c..773bc4f26b 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -174,10 +174,6 @@ public SqlConnection(string connectionString, SqlCredential credential) : this() { throw ADP.InvalidMixedArgumentOfSecureCredentialAndIntegratedSecurity(); } - else if (UsesContextConnection(connectionOptions)) - { - throw ADP.InvalidMixedArgumentOfSecureCredentialAndContextConnection(); - } else if (UsesActiveDirectoryIntegrated(connectionOptions)) { throw SQL.SettingCredentialWithIntegratedArgument(); @@ -459,49 +455,39 @@ public bool StatisticsEnabled } set { - if (IsContextConnection) + if (value) { - if (value) + // start + if (ConnectionState.Open == State) { - throw SQL.NotAvailableOnContextConnection(); + if (_statistics == null) + { + _statistics = new SqlStatistics(); + _statistics._openTimestamp = ADP.TimerCurrent(); + } + // set statistics on the parser + // update timestamp; + Debug.Assert(Parser != null, "Where's the parser?"); + Parser.Statistics = _statistics; } } else { - if (value) + // stop + if (_statistics != null) { - // start if (ConnectionState.Open == State) { - if (_statistics == null) - { - _statistics = new SqlStatistics(); - _statistics._openTimestamp = ADP.TimerCurrent(); - } - // set statistics on the parser + // remove statistics from parser // update timestamp; - Debug.Assert(Parser != null, "Where's the parser?"); - Parser.Statistics = _statistics; + TdsParser parser = Parser; + Debug.Assert(parser != null, "Where's the parser?"); + parser.Statistics = null; + _statistics._closeTimestamp = ADP.TimerCurrent(); } } - else - { - // stop - if (_statistics != null) - { - if (ConnectionState.Open == State) - { - // remove statistics from parser - // update timestamp; - TdsParser parser = Parser; - Debug.Assert(parser != null, "Where's the parser?"); - parser.Statistics = null; - _statistics._closeTimestamp = ADP.TimerCurrent(); - } - } - } - _collectstats = value; } + _collectstats = value; } } @@ -512,21 +498,6 @@ internal bool AsyncCommandInProgress set => _AsyncCommandInProgress = value; } - internal bool IsContextConnection - { - get - { - SqlConnectionString opt = (SqlConnectionString)ConnectionOptions; - return UsesContextConnection(opt); - } - } - - // Is this connection is a Context Connection? - private bool UsesContextConnection(SqlConnectionString opt) - { - return opt != null && opt.ContextConnection; - } - private bool UsesActiveDirectoryIntegrated(SqlConnectionString opt) { return opt != null && opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated; @@ -868,15 +839,8 @@ public int PacketSize // can just return what the connection string had. get { - if (IsContextConnection) - { - throw SQL.NotAvailableOnContextConnection(); - } - - SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); int result; - - if (innerConnection != null) + if (InnerConnection is SqlInternalConnectionTds innerConnection) { result = innerConnection.PacketSize; } @@ -885,6 +849,7 @@ public int PacketSize SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; result = constr != null ? constr.PacketSize : SqlConnectionString.DEFAULT.Packet_Size; } + return result; } } @@ -970,11 +935,6 @@ public string WorkstationId { get { - if (IsContextConnection) - { - throw SQL.NotAvailableOnContextConnection(); - } - // If not supplied by the user, the default value is the MachineName // Note: In Longhorn you'll be able to rename a machine without // rebooting. Therefore, don't cache this machine name. @@ -1086,11 +1046,6 @@ private void CheckAndThrowOnInvalidCombinationOfConnectionStringAndSqlCredential { throw ADP.InvalidMixedUsageOfSecureCredentialAndIntegratedSecurity(); } - - if (UsesContextConnection(connectionOptions)) - { - throw ADP.InvalidMixedArgumentOfSecureCredentialAndContextConnection(); - } } // CheckAndThrowOnInvalidCombinationOfConnectionOptionAndAccessToken: check if the usage of AccessToken has any conflict @@ -1109,11 +1064,6 @@ private void CheckAndThrowOnInvalidCombinationOfConnectionOptionAndAccessToken(S throw ADP.InvalidMixedUsageOfAccessTokenAndIntegratedSecurity(); } - if (UsesContextConnection(connectionOptions)) - { - throw ADP.InvalidMixedUsageOfAccessTokenAndContextConnection(); - } - if (UsesAuthentication(connectionOptions)) { throw ADP.InvalidMixedUsageOfAccessTokenAndAuthentication(); @@ -1328,10 +1278,6 @@ public static void ClearPool(SqlConnection connection) if (connectionOptions != null) { connectionOptions.DemandPermission(); - if (connection.IsContextConnection) - { - throw SQL.NotAvailableOnContextConnection(); - } SqlConnectionFactory.SingletonInstance.ClearPool(connection); } } @@ -1446,21 +1392,12 @@ private void DisposeMe(bool disposing) } /// - public void EnlistDistributedTransaction(System.EnterpriseServices.ITransaction transaction) - { - if (IsContextConnection) - { - throw SQL.NotAvailableOnContextConnection(); - } - + public void EnlistDistributedTransaction(System.EnterpriseServices.ITransaction transaction) => EnlistDistributedTransactionHelper(transaction); - } /// - public override void Open() - { + public override void Open() => Open(SqlConnectionOverrides.None); - } private bool TryOpenWithRetry(TaskCompletionSource retry, SqlConnectionOverrides overrides) => RetryLogicProvider.Execute(this, () => TryOpen(retry, overrides)); @@ -1773,13 +1710,6 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok return result.Task; } - if (IsContextConnection) - { - // Async not supported on Context Connections - result.SetException(ADP.ExceptionWithStackTrace(SQL.NotAvailableOnContextConnection())); - return result.Task; - } - bool completed; try @@ -2275,12 +2205,8 @@ public static void ChangePassword(string connectionString, string newPassword) { throw SQL.ChangePasswordUseOfUnallowedKey(SqlConnectionString.KEY.AttachDBFilename); } - if (connectionOptions.ContextConnection) - { - throw SQL.ChangePasswordUseOfUnallowedKey(SqlConnectionString.KEY.Context_Connection); - } - System.Security.PermissionSet permissionSet = connectionOptions.CreatePermissionSet(); + PermissionSet permissionSet = connectionOptions.CreatePermissionSet(); permissionSet.Demand(); ChangePassword(connectionString, connectionOptions, null, newPassword, null); @@ -2340,12 +2266,7 @@ public static void ChangePassword(string connectionString, SqlCredential credent throw SQL.ChangePasswordUseOfUnallowedKey(SqlConnectionString.KEY.AttachDBFilename); } - if (connectionOptions.ContextConnection) - { - throw SQL.ChangePasswordUseOfUnallowedKey(SqlConnectionString.KEY.Context_Connection); - } - - System.Security.PermissionSet permissionSet = connectionOptions.CreatePermissionSet(); + PermissionSet permissionSet = connectionOptions.CreatePermissionSet(); permissionSet.Demand(); ChangePassword(connectionString, connectionOptions, credential, null, newSecurePassword); @@ -2419,11 +2340,6 @@ internal Task RegisterForConnectionCloseNotification(Task outerTask, ob /// public void ResetStatistics() { - if (IsContextConnection) - { - throw SQL.NotAvailableOnContextConnection(); - } - if (Statistics != null) { Statistics.Reset(); @@ -2438,11 +2354,6 @@ public void ResetStatistics() /// public IDictionary RetrieveStatistics() { - if (IsContextConnection) - { - throw SQL.NotAvailableOnContextConnection(); - } - if (Statistics != null) { UpdateStatistics(); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs index bf6f4d759e..a8f3a83096 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs @@ -40,7 +40,6 @@ override protected DbConnectionInternal CreateConnection(DbConnectionOptions opt { SqlConnectionString opt = (SqlConnectionString)options; SqlConnectionPoolKey key = (SqlConnectionPoolKey)poolKey; - SqlInternalConnection result = null; SessionData recoverySessionData = null; SqlConnection sqlOwningConnection = owningConnection as SqlConnection; bool applyTransientFaultHandling = sqlOwningConnection != null ? sqlOwningConnection._applyTransientFaultHandling : false; @@ -59,93 +58,102 @@ override protected DbConnectionInternal CreateConnection(DbConnectionOptions opt { recoverySessionData = sqlOwningConnection._recoverySessionData; } + + bool redirectedUserInstance = false; + DbConnectionPoolIdentity identity = null; - if (opt.ContextConnection) + // Pass DbConnectionPoolIdentity to SqlInternalConnectionTds if using integrated security. + // Used by notifications. + if (opt.IntegratedSecurity || opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated) { - 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 || opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated) + if (pool != null) { - if (pool != null) - { - identity = pool.Identity; - } - else - { - identity = DbConnectionPoolIdentity.GetCurrent(); - } + identity = pool.Identity; } - - // 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) + else { - // opt.DataSource is used to create the SSE connection - redirectedUserInstance = true; - string instanceName; + identity = DbConnectionPoolIdentity.GetCurrent(); + } + } - if (pool == null || (pool != null && pool.Count <= 0)) - { // Non-pooled or pooled and no connections in the pool. + // 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 (pool == null || (pool != null && pool.Count <= 0)) + { // Non-pooled or pooled and no connections in the pool. - SqlInternalConnectionTds sseConnection = null; - try + SqlInternalConnectionTds sseConnection = null; + try + { + // What about a failure - throw? YES! + // BUG (VSTFDevDiv) 479687: Using TransactionScope with Linq2SQL against user instances fails with "connection has been broken" message + // NOTE: Cloning connection option opt to set 'UserInstance=True' and 'Enlist=False' + // This first connection is established to SqlExpress to get the instance name + // of the UserInstance. + 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, applyTransientFaultHandling: applyTransientFaultHandling); + // NOTE: Retrieve here. This user instance name will be used below to connect to the Sql Express User Instance. + instanceName = sseConnection.InstanceName; + + // Set future transient fault handling based on connection options + sqlOwningConnection._applyTransientFaultHandling = opt != null && opt.ConnectRetryCount > 0; + + if (!instanceName.StartsWith("\\\\.\\", StringComparison.Ordinal)) { - // What about a failure - throw? YES! - // BUG (VSTFDevDiv) 479687: Using TransactionScope with Linq2SQL against user instances fails with "connection has been broken" message - // NOTE: Cloning connection option opt to set 'UserInstance=True' and 'Enlist=False' - // This first connection is established to SqlExpress to get the instance name - // of the UserInstance. - 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, applyTransientFaultHandling: applyTransientFaultHandling); - // NOTE: Retrieve here. This user instance name will be used below to connect to the Sql Express User Instance. - instanceName = sseConnection.InstanceName; - - // Set future transient fault handling based on connection options - sqlOwningConnection._applyTransientFaultHandling = opt != null && opt.ConnectRetryCount > 0; - - if (!instanceName.StartsWith("\\\\.\\", StringComparison.Ordinal)) - { - throw SQL.NonLocalSSEInstance(); - } - - if (pool != null) - { // Pooled connection - cache result - SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo)pool.ProviderInfo; - // No lock since we are already in creation mutex - providerInfo.InstanceName = instanceName; - } + throw SQL.NonLocalSSEInstance(); } - finally - { - if (sseConnection != null) - { - sseConnection.Dispose(); - } + + if (pool != null) + { // Pooled connection - cache result + SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo)pool.ProviderInfo; + // No lock since we are already in creation mutex + providerInfo.InstanceName = instanceName; } } - else - { // Cached info from pool. - SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo)pool.ProviderInfo; - // No lock since we are already in creation mutex - instanceName = providerInfo.InstanceName; + finally + { + if (sseConnection != null) + { + sseConnection.Dispose(); + } } - - // NOTE: Here connection option opt is cloned to set 'instanceName=' 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, applyTransientFaultHandling, key.AccessToken, pool, key.AccessTokenCallback); + 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=' 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, + userInstance: false, + setEnlistValue: null); // Do not modify the enlist value } - return result; + + return new SqlInternalConnectionTds( + identity, + opt, + key.Credential, + providerInfo: null, + newPassword: string.Empty, + newSecurePassword: null, + redirectedUserInstance, + userOpt, + recoverySessionData, + applyTransientFaultHandling, + key.AccessToken, + pool, + key.AccessTokenCallback); } protected override DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous) @@ -167,20 +175,24 @@ override internal DbConnectionPoolProviderInfo CreateConnectionPoolProviderInfo( return providerInfo; } - override protected DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions(DbConnectionOptions connectionOptions) + protected override DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions(DbConnectionOptions connectionOptions) { SqlConnectionString opt = (SqlConnectionString)connectionOptions; DbConnectionPoolGroupOptions poolingOptions = null; - if (!opt.ContextConnection && opt.Pooling) + if (opt.Pooling) { // never pool context connections. int connectionTimeout = opt.ConnectTimeout; - if ((0 < connectionTimeout) && (connectionTimeout < Int32.MaxValue / 1000)) + if (connectionTimeout > 0 && connectionTimeout < int.MaxValue / 1000) + { connectionTimeout *= 1000; - else if (connectionTimeout >= Int32.MaxValue / 1000) - connectionTimeout = Int32.MaxValue; + } + else if (connectionTimeout >= int.MaxValue / 1000) + { + connectionTimeout = int.MaxValue; + } if (opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryInteractive) { @@ -241,29 +253,6 @@ internal static SqlConnectionString FindSqlConnectionOptions(SqlConnectionPoolKe return connectionOptions; } - 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 (result == null || result.IsConnectionDoomed) - { - if (result != null) - { - 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; - } - override internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnection connection) { SqlConnection c = (connection as SqlConnection); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDataReaderSmi.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDataReaderSmi.cs index 95a45c428d..faef28fb3d 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDataReaderSmi.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDataReaderSmi.cs @@ -1058,6 +1058,7 @@ internal enum PositionState private SqlSequentialStreamSmi _currentStream; // The stream on the current column (if any) private SqlSequentialTextReaderSmi _currentTextReader; // The text reader on the current column (if any) + // @TODO: No longer used -- delete! // Assumes that if there were any results, the first chunk of them are in the data stream // (up to the first actual row or the end of the resultsets). unsafe internal SqlDataReaderSmi( diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionSmi.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionSmi.cs index 59181ff602..9251696dfa 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionSmi.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionSmi.cs @@ -108,6 +108,7 @@ internal override void TransactionStarted(long transactionId) } } + // @TODO: No longer used -- delete! internal SqlInternalConnectionSmi(SqlConnectionString connectionOptions, SmiContext smiContext) : base(connectionOptions) { Debug.Assert(smiContext != null, "null smiContext?"); @@ -235,6 +236,7 @@ override protected void Activate(Transaction transaction) Debug.Assert(false, "Activating an internal SMI connection?"); // we should never be activating, because that would indicate we're being pooled. } + // @TODO: No longer used -- delete internal void Activate() { int wasInUse = System.Threading.Interlocked.Exchange(ref _isInUse, 1); @@ -424,6 +426,7 @@ override protected byte[] GetDTCAddress() return whereAbouts; } + // @TODO: No longer used -- delete! internal void GetCurrentTransactionPair(out long transactionId, out Transaction transaction) { // SQLBU 214740: Transaction state could change between obtaining tranid and transaction diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index c5bf4fe9db..bfb5b13997 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -529,9 +529,7 @@ internal SqlInternalConnectionTds( _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; diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiContext.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiContext.netfx.cs index 1f2ef3031a..f7a78446f2 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiContext.netfx.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiContext.netfx.cs @@ -15,9 +15,9 @@ namespace Microsoft.Data.SqlClient.Server // NOTE: connection, transaction and context pipe operations could be // encapsulated in their own classes, and should if they get complex // (transaction is borderline at this point). + // @TODO: This doesn't seem to be inherited from anymore... internal abstract class SmiContext { - internal abstract event EventHandler OutOfScope; internal abstract SmiConnection ContextConnection { get; } @@ -35,6 +35,7 @@ internal abstract SmiRecordBuffer CreateRecordBuffer( SmiEventSink eventSink ); + // @TODO: No longer being used - delete! internal abstract SmiRequestExecutor CreateRequestExecutor( string commandText, CommandType commandType, @@ -42,8 +43,6 @@ internal abstract SmiRequestExecutor CreateRequestExecutor( SmiEventSink eventSink ); - internal abstract object GetContextValue(int key); - internal abstract void GetTriggerInfo( SmiEventSink eventSink, out bool[] columnsUpdated, @@ -59,8 +58,6 @@ out SqlXml eventInstanceData internal abstract void SendResultsEndToPipe(SmiRecordBuffer recordBuffer, SmiEventSink eventSink); - internal abstract void SetContextValue(int key, object value); - // Scratch LOB storage region internal virtual SmiStream GetScratchStream(SmiEventSink sink) { diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventStream.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventStream.netfx.cs index 91d0bd798f..cfdcc1bb3d 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventStream.netfx.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventStream.netfx.cs @@ -8,6 +8,7 @@ namespace Microsoft.Data.SqlClient.Server { + // @TODO: Is this implemented *anywhere*? internal abstract class SmiEventStream : IDisposable { internal abstract bool HasEvents { get; } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiRequestExecutor.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiRequestExecutor.netfx.cs index 17ad326ae2..62411c2b1f 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiRequestExecutor.netfx.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiRequestExecutor.netfx.cs @@ -23,6 +23,7 @@ public virtual void Close(SmiEventSink eventSink) throw Common.ADP.InternalError(Common.ADP.InternalErrorCode.UnimplementedSMIMethod); } + // @TODO: No longer used -- delete! internal virtual SmiEventStream Execute( SmiConnection connection, // Assigned connection long transactionId, // Assigned transaction @@ -39,6 +40,7 @@ internal virtual SmiEventStream Execute( throw Common.ADP.InternalError(Common.ADP.InternalErrorCode.UnimplementedSMIMethod); } + // @TODO: No longer used -- delete! internal virtual SmiEventStream Execute( SmiConnection connection, // Assigned connection long transactionId, // Assigned transaction @@ -62,6 +64,7 @@ internal virtual SmiEventStream Execute( // SmiRequestExecutor and it's subclasses should NOT override Getters from SmiTypedGetterSetter // Calls against those methods on a Request Executor are not allowed. + // @TODO: No longer used -- delete! // Set DEFAULT bit for parameter internal abstract void SetDefault(int ordinal); diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs index 245ea3e45f..7f1e8cf72b 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs @@ -697,9 +697,6 @@ internal SqlConnectionString(SqlConnectionString connectionOptions, string dataS internal ApplicationIntent ApplicationIntent => _applicationIntent; internal string ApplicationName => _applicationName; internal string AttachDBFilename => _attachDBFileName; - // Return a constant value rather than _contextConnection. This allows the JIT to trim - // the code paths referencing it. - internal bool ContextConnection => false; internal string CurrentLanguage => _currentLanguage; internal string DataSource => _dataSource; internal string LocalDBInstance => _localDBInstance;