diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs index 5a877d61e9..edf9fd78e6 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs @@ -258,11 +258,31 @@ internal _SqlMetaDataSet MetaData throw SQL.PendingBeginXXXExists(); } - Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); - if (TryConsumeMetaData() != TdsOperationStatus.Done) +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try { - throw SQL.SynchronousCallMayNotPend(); + tdsReliabilitySection.Start(); +#else + { +#endif + Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); + if (TryConsumeMetaData() != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } + } +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); } +#endif } return _metaData; } @@ -837,9 +857,29 @@ private void CleanPartialReadReliable() { AssertReaderState(requireData: true, permitAsync: false); - TdsOperationStatus result = TryCleanPartialRead(); - Debug.Assert(result == TdsOperationStatus.Done, "Should not pend on sync call"); - Debug.Assert(!_sharedState._dataReady, "_dataReady should be cleared"); +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + tdsReliabilitySection.Start(); +#else + { +#endif + TdsOperationStatus result = TryCleanPartialRead(); + Debug.Assert(result == TdsOperationStatus.Done, "Should not pend on sync call"); + Debug.Assert(!_sharedState._dataReady, "_dataReady should be cleared"); + } +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); + } +#endif } /// @@ -959,62 +999,82 @@ private TdsOperationStatus TryCloseInternal(bool closeReader) bool cleanDataFailed = false; TdsOperationStatus result; +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif try { - if ((!_isClosed) && (parser != null) && (stateObj != null) && (stateObj.HasPendingData)) +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try { - // It is possible for this to be called during connection close on a - // broken connection, so check state first. - if (parser.State == TdsParserState.OpenLoggedIn) + tdsReliabilitySection.Start(); +#else + { +#endif + if ((!_isClosed) && (parser != null) && (stateObj != null) && (stateObj.HasPendingData)) { - // if user called read but didn't fetch any values, skip the row - // same applies after NextResult on ALTROW because NextResult starts rowconsumption in that case ... + // It is possible for this to be called during connection close on a + // broken connection, so check state first. + if (parser.State == TdsParserState.OpenLoggedIn) + { + // if user called read but didn't fetch any values, skip the row + // same applies after NextResult on ALTROW because NextResult starts rowconsumption in that case ... - Debug.Assert(SniContext.Snix_Read == stateObj.SniContext, $"The SniContext should be Snix_Read but it actually is {stateObj.SniContext}"); + Debug.Assert(SniContext.Snix_Read == stateObj.SniContext, $"The SniContext should be Snix_Read but it actually is {stateObj.SniContext}"); - if (_altRowStatus == ALTROWSTATUS.AltRow) - { - _sharedState._dataReady = true; // set _sharedState._dataReady to not confuse CleanPartialRead - } - _stateObj.SetTimeoutStateStopped(); - if (_sharedState._dataReady) - { - cleanDataFailed = true; - result = TryCleanPartialRead(); - if (result == TdsOperationStatus.Done) + if (_altRowStatus == ALTROWSTATUS.AltRow) { - cleanDataFailed = false; + _sharedState._dataReady = true; // set _sharedState._dataReady to not confuse CleanPartialRead } - else + _stateObj.SetTimeoutStateStopped(); + if (_sharedState._dataReady) { - return result; + cleanDataFailed = true; + result = TryCleanPartialRead(); + if (result == TdsOperationStatus.Done) + { + cleanDataFailed = false; + } + else + { + return result; + } } - } #if DEBUG - else - { - byte token; - result = _stateObj.TryPeekByte(out token); - if (result != TdsOperationStatus.Done) + else { - return result; - } + byte token; + result = _stateObj.TryPeekByte(out token); + if (result != TdsOperationStatus.Done) + { + return result; + } - Debug.Assert(TdsParser.IsValidTdsToken(token), $"DataReady is false, but next token is invalid: {token,-2:X2}"); - } + Debug.Assert(TdsParser.IsValidTdsToken(token), $"DataReady is false, but next token is invalid: {token,-2:X2}"); + } #endif - result = parser.TryRun(RunBehavior.Clean, _command, this, null, stateObj, out _); - if (result != TdsOperationStatus.Done) - { - return result; + result = parser.TryRun(RunBehavior.Clean, _command, this, null, stateObj, out _); + if (result != TdsOperationStatus.Done) + { + return result; + } } } - } - RestoreServerSettings(parser, stateObj); - return TdsOperationStatus.Done; + RestoreServerSettings(parser, stateObj); + return TdsOperationStatus.Done; + } +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); + } +#endif } finally { @@ -1054,25 +1114,44 @@ private TdsOperationStatus TryCloseInternal(bool closeReader) Connection.RemoveWeakReference(this); // This doesn't catch everything -- the connection may be closed, but it prevents dead readers from clogging the collection } +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); - // IsClosed may be true if CloseReaderFromConnection was called - in which case, the session has already been closed - if (!wasClosed && stateObj != null) + RuntimeHelpers.PrepareConstrainedRegions(); + try { - if (!cleanDataFailed) - { - stateObj.CloseSession(); - } - else + tdsReliabilitySection.Start(); +#else + { +#endif + // IsClosed may be true if CloseReaderFromConnection was called - in which case, the session has already been closed + if (!wasClosed && stateObj != null) { - if (parser != null) + if (!cleanDataFailed) + { + stateObj.CloseSession(); + } + else { - parser.State = TdsParserState.Broken; // We failed while draining data, so TDS pointer can be between tokens - cannot recover - parser.PutSession(stateObj); - parser.Connection.BreakConnection(); + if (parser != null) + { + parser.State = TdsParserState.Broken; // We failed while draining data, so TDS pointer can be between tokens - cannot recover + parser.PutSession(stateObj); + parser.Connection.BreakConnection(); + } } } + // DO NOT USE stateObj after this point - it has been returned to the TdsParser's session pool and potentially handed out to another thread } - // DO NOT USE stateObj after this point - it has been returned to the TdsParser's session pool and potentially handed out to another thread +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); + } +#endif // do not retry here result = TrySetMetaData(null, false); @@ -1654,231 +1733,251 @@ private TdsOperationStatus TryGetBytesInternal(int i, long dataIndex, byte[] buf { remaining = 0; TdsOperationStatus result; - int cbytes = 0; - AssertReaderState(requireData: true, permitAsync: true, columnIndex: i, enforceSequentialAccess: true); +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); - // sequential reading - if (IsCommandBehavior(CommandBehavior.SequentialAccess)) + RuntimeHelpers.PrepareConstrainedRegions(); + try { - Debug.Assert(!HasActiveStreamOrTextReaderOnColumn(i), "Column has an active Stream or TextReader"); + tdsReliabilitySection.Start(); +#else + { +#endif + int cbytes = 0; + AssertReaderState(requireData: true, permitAsync: true, columnIndex: i, enforceSequentialAccess: true); - if (_metaData[i] != null && _metaData[i].cipherMD != null) + // sequential reading + if (IsCommandBehavior(CommandBehavior.SequentialAccess)) { - throw SQL.SequentialAccessNotSupportedOnEncryptedColumn(_metaData[i].column); - } + Debug.Assert(!HasActiveStreamOrTextReaderOnColumn(i), "Column has an active Stream or TextReader"); - if (_sharedState._nextColumnHeaderToRead <= i) - { - result = TryReadColumnHeader(i); - if (result != TdsOperationStatus.Done) + if (_metaData[i] != null && _metaData[i].cipherMD != null) { - return result; + throw SQL.SequentialAccessNotSupportedOnEncryptedColumn(_metaData[i].column); } - } - // If data is null, ReadColumnHeader sets the data.IsNull bit. - if (_data[i] != null && _data[i].IsNull) - { - throw new SqlNullValueException(); - } + if (_sharedState._nextColumnHeaderToRead <= i) + { + result = TryReadColumnHeader(i); + if (result != TdsOperationStatus.Done) + { + return result; + } + } - // If there are an unknown (-1) number of bytes left for a PLP, read its size - if ((-1 == _sharedState._columnDataBytesRemaining) && (_metaData[i].metaType.IsPlp)) - { - ulong left; - result = _parser.TryPlpBytesLeft(_stateObj, out left); - if (result != TdsOperationStatus.Done) + // If data is null, ReadColumnHeader sets the data.IsNull bit. + if (_data[i] != null && _data[i].IsNull) { - return result; + throw new SqlNullValueException(); } - _sharedState._columnDataBytesRemaining = (long)left; - } - if (0 == _sharedState._columnDataBytesRemaining) - { - return TdsOperationStatus.Done; // We've read this column to the end - } + // If there are an unknown (-1) number of bytes left for a PLP, read its size + if ((-1 == _sharedState._columnDataBytesRemaining) && (_metaData[i].metaType.IsPlp)) + { + ulong left; + result = _parser.TryPlpBytesLeft(_stateObj, out left); + if (result != TdsOperationStatus.Done) + { + return result; + } + _sharedState._columnDataBytesRemaining = (long)left; + } - // if no buffer is passed in, return the number total of bytes, or -1 - if (buffer == null) - { - if (_metaData[i].metaType.IsPlp) + if (0 == _sharedState._columnDataBytesRemaining) { - remaining = (long)_parser.PlpBytesTotalLength(_stateObj); + return TdsOperationStatus.Done; // We've read this column to the end + } + + // if no buffer is passed in, return the number total of bytes, or -1 + if (buffer == null) + { + if (_metaData[i].metaType.IsPlp) + { + remaining = (long)_parser.PlpBytesTotalLength(_stateObj); + return TdsOperationStatus.Done; + } + remaining = _sharedState._columnDataBytesRemaining; return TdsOperationStatus.Done; } - remaining = _sharedState._columnDataBytesRemaining; - return TdsOperationStatus.Done; - } - if (dataIndex < 0) - { - throw ADP.NegativeParameter(nameof(dataIndex)); - } + if (dataIndex < 0) + { + throw ADP.NegativeParameter(nameof(dataIndex)); + } - if (dataIndex < _columnDataBytesRead) - { - throw ADP.NonSeqByteAccess(dataIndex, _columnDataBytesRead, nameof(GetBytes)); - } + if (dataIndex < _columnDataBytesRead) + { + throw ADP.NonSeqByteAccess(dataIndex, _columnDataBytesRead, nameof(GetBytes)); + } - // if the dataIndex is not equal to bytes read, then we have to skip bytes - long cb = dataIndex - _columnDataBytesRead; + // if the dataIndex is not equal to bytes read, then we have to skip bytes + long cb = dataIndex - _columnDataBytesRead; - // if dataIndex is outside of the data range, return 0 - if ((cb > _sharedState._columnDataBytesRemaining) && !_metaData[i].metaType.IsPlp) - { - return TdsOperationStatus.Done; - } + // if dataIndex is outside of the data range, return 0 + if ((cb > _sharedState._columnDataBytesRemaining) && !_metaData[i].metaType.IsPlp) + { + return TdsOperationStatus.Done; + } - // if bad buffer index, throw - if (bufferIndex < 0 || bufferIndex >= buffer.Length) - { - throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, nameof(bufferIndex)); - } + // if bad buffer index, throw + if (bufferIndex < 0 || bufferIndex >= buffer.Length) + { + throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, nameof(bufferIndex)); + } - // if there is not enough room in the buffer for data - if (length + bufferIndex > buffer.Length) - { - throw ADP.InvalidBufferSizeOrIndex(length, bufferIndex); - } + // if there is not enough room in the buffer for data + if (length + bufferIndex > buffer.Length) + { + throw ADP.InvalidBufferSizeOrIndex(length, bufferIndex); + } - if (length < 0) - { - throw ADP.InvalidDataLength(length); - } + if (length < 0) + { + throw ADP.InvalidDataLength(length); + } - // Skip if needed - if (cb > 0) - { - if (_metaData[i].metaType.IsPlp) + // Skip if needed + if (cb > 0) { - ulong skipped; - result = _parser.TrySkipPlpValue((ulong)cb, _stateObj, out skipped); - if (result != TdsOperationStatus.Done) + if (_metaData[i].metaType.IsPlp) { - return result; + ulong skipped; + result = _parser.TrySkipPlpValue((ulong)cb, _stateObj, out skipped); + if (result != TdsOperationStatus.Done) + { + return result; + } + _columnDataBytesRead += (long)skipped; } - _columnDataBytesRead += (long)skipped; - } - else - { - result = _stateObj.TrySkipLongBytes(cb); - if (result != TdsOperationStatus.Done) + else { - return result; + result = _stateObj.TrySkipLongBytes(cb); + if (result != TdsOperationStatus.Done) + { + return result; + } + _columnDataBytesRead += cb; + _sharedState._columnDataBytesRemaining -= cb; } - _columnDataBytesRead += cb; - _sharedState._columnDataBytesRemaining -= cb; } - } - int bytesRead; - result = TryGetBytesInternalSequential(i, buffer, bufferIndex, length, out bytesRead); - remaining = (int)bytesRead; - return result; - } - - // random access now! - // note that since we are caching in an array, and arrays aren't 64 bit ready yet, - // we need can cast to int if the dataIndex is in range - if (dataIndex < 0) - { - throw ADP.NegativeParameter(nameof(dataIndex)); - } + int bytesRead; + result = TryGetBytesInternalSequential(i, buffer, bufferIndex, length, out bytesRead); + remaining = (int)bytesRead; + return result; + } - if (dataIndex > int.MaxValue) - { - throw ADP.InvalidSourceBufferIndex(cbytes, dataIndex, nameof(dataIndex)); - } + // random access now! + // note that since we are caching in an array, and arrays aren't 64 bit ready yet, + // we need can cast to int if the dataIndex is in range + if (dataIndex < 0) + { + throw ADP.NegativeParameter(nameof(dataIndex)); + } - int ndataIndex = (int)dataIndex; - byte[] data; + if (dataIndex > int.MaxValue) + { + throw ADP.InvalidSourceBufferIndex(cbytes, dataIndex, nameof(dataIndex)); + } - // WebData 99342 - in the non-sequential case, we need to support - // the use of GetBytes on string data columns, but - // GetSqlBinary isn't supposed to. What we end up - // doing isn't exactly pretty, but it does work. - if (_metaData[i].metaType.IsBinType) - { - data = GetSqlBinary(i).Value; - } - else - { - Debug.Assert(_metaData[i].metaType.IsLong, "non long type?"); - Debug.Assert(_metaData[i].metaType.IsCharType, "non-char type?"); + int ndataIndex = (int)dataIndex; + byte[] data; - SqlString temp = GetSqlString(i); - if (_metaData[i].metaType.IsNCharType) + // WebData 99342 - in the non-sequential case, we need to support + // the use of GetBytes on string data columns, but + // GetSqlBinary isn't supposed to. What we end up + // doing isn't exactly pretty, but it does work. + if (_metaData[i].metaType.IsBinType) { - data = temp.GetUnicodeBytes(); + data = GetSqlBinary(i).Value; } else { - data = temp.GetNonUnicodeBytes(); - } - } - - cbytes = data.Length; + Debug.Assert(_metaData[i].metaType.IsLong, "non long type?"); + Debug.Assert(_metaData[i].metaType.IsCharType, "non-char type?"); - // if no buffer is passed in, return the number of characters we have - if (buffer == null) - { - remaining = cbytes; - return TdsOperationStatus.Done; - } - - // if dataIndex is outside of data range, return 0 - if (ndataIndex < 0 || ndataIndex >= cbytes) - { - return TdsOperationStatus.Done; - } - try - { - if (ndataIndex < cbytes) - { - // help the user out in the case where there's less data than requested - if ((ndataIndex + length) > cbytes) + SqlString temp = GetSqlString(i); + if (_metaData[i].metaType.IsNCharType) { - cbytes = cbytes - ndataIndex; + data = temp.GetUnicodeBytes(); } else { - cbytes = length; + data = temp.GetNonUnicodeBytes(); } } - Buffer.BlockCopy(data, ndataIndex, buffer, bufferIndex, cbytes); - } - catch (Exception e) - { - if (!ADP.IsCatchableExceptionType(e)) - { - throw; - } cbytes = data.Length; - if (length < 0) + // if no buffer is passed in, return the number of characters we have + if (buffer == null) { - throw ADP.InvalidDataLength(length); + remaining = cbytes; + return TdsOperationStatus.Done; } - // if bad buffer index, throw - if (bufferIndex < 0 || bufferIndex >= buffer.Length) + // if dataIndex is outside of data range, return 0 + if (ndataIndex < 0 || ndataIndex >= cbytes) { - throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, nameof(bufferIndex)); + return TdsOperationStatus.Done; } + try + { + if (ndataIndex < cbytes) + { + // help the user out in the case where there's less data than requested + if ((ndataIndex + length) > cbytes) + { + cbytes = cbytes - ndataIndex; + } + else + { + cbytes = length; + } + } - // if there is not enough room in the buffer for data - if (cbytes + bufferIndex > buffer.Length) + Buffer.BlockCopy(data, ndataIndex, buffer, bufferIndex, cbytes); + } + catch (Exception e) { - throw ADP.InvalidBufferSizeOrIndex(cbytes, bufferIndex); + if (!ADP.IsCatchableExceptionType(e)) + { + throw; + } + cbytes = data.Length; + + if (length < 0) + { + throw ADP.InvalidDataLength(length); + } + + // if bad buffer index, throw + if (bufferIndex < 0 || bufferIndex >= buffer.Length) + { + throw ADP.InvalidDestinationBufferIndex(buffer.Length, bufferIndex, nameof(bufferIndex)); + } + + // if there is not enough room in the buffer for data + if (cbytes + bufferIndex > buffer.Length) + { + throw ADP.InvalidBufferSizeOrIndex(cbytes, bufferIndex); + } + + throw; } - throw; + remaining = cbytes; + return TdsOperationStatus.Done; } - - remaining = cbytes; - return TdsOperationStatus.Done; +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); + } +#endif //DEBUG } internal int GetBytesInternalSequential(int i, byte[] buffer, int index, int length, long? timeoutMilliseconds = null) @@ -1930,46 +2029,66 @@ internal TdsOperationStatus TryGetBytesInternalSequential(int i, byte[] buffer, bytesRead = 0; TdsOperationStatus result; - if ((_sharedState._columnDataBytesRemaining == 0) || (length == 0)) +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try { - // No data left or nothing requested, return 0 - bytesRead = 0; - return TdsOperationStatus.Done; - } - else + tdsReliabilitySection.Start(); +#else { - // if plp columns, do partial reads. Don't read the entire value in one shot. - if (_metaData[i].metaType.IsPlp) +#endif + if ((_sharedState._columnDataBytesRemaining == 0) || (length == 0)) { - // Read in data - result = _stateObj.TryReadPlpBytes(ref buffer, index, length, out bytesRead); - _columnDataBytesRead += bytesRead; - if (result != TdsOperationStatus.Done) + // No data left or nothing requested, return 0 + bytesRead = 0; + return TdsOperationStatus.Done; + } + else + { + // if plp columns, do partial reads. Don't read the entire value in one shot. + if (_metaData[i].metaType.IsPlp) { - return result; - } + // Read in data + result = _stateObj.TryReadPlpBytes(ref buffer, index, length, out bytesRead); + _columnDataBytesRead += bytesRead; + if (result != TdsOperationStatus.Done) + { + return result; + } - // Query for number of bytes left - ulong left; - result = _parser.TryPlpBytesLeft(_stateObj, out left); - if (result != TdsOperationStatus.Done) + // Query for number of bytes left + ulong left; + result = _parser.TryPlpBytesLeft(_stateObj, out left); + if (result != TdsOperationStatus.Done) + { + _sharedState._columnDataBytesRemaining = -1; + return result; + } + _sharedState._columnDataBytesRemaining = (long)left; + return TdsOperationStatus.Done; + } + else { - _sharedState._columnDataBytesRemaining = -1; + // Read data (not exceeding the total amount of data available) + int bytesToRead = (int)Math.Min((long)length, _sharedState._columnDataBytesRemaining); + result = _stateObj.TryReadByteArray(buffer.AsSpan(index), bytesToRead, out bytesRead); + _columnDataBytesRead += bytesRead; + _sharedState._columnDataBytesRemaining -= bytesRead; return result; } - _sharedState._columnDataBytesRemaining = (long)left; - return TdsOperationStatus.Done; - } - else - { - // Read data (not exceeding the total amount of data available) - int bytesToRead = (int)Math.Min((long)length, _sharedState._columnDataBytesRemaining); - result = _stateObj.TryReadByteArray(buffer.AsSpan(index), bytesToRead, out bytesRead); - _columnDataBytesRead += bytesRead; - _sharedState._columnDataBytesRemaining -= bytesRead; - return result; } } +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); + } +#endif } /// @@ -2241,93 +2360,113 @@ override public long GetChars(int i, long dataIndex, char[] buffer, int bufferIn private long GetCharsFromPlpData(int i, long dataIndex, char[] buffer, int bufferIndex, int length) { - long cch; - - AssertReaderState(requireData: true, permitAsync: false, columnIndex: i, enforceSequentialAccess: true); - Debug.Assert(!HasActiveStreamOrTextReaderOnColumn(i), "Column has active Stream or TextReader"); - // don't allow get bytes on non-long or non-binary columns - Debug.Assert(_metaData[i].metaType.IsPlp, "GetCharsFromPlpData called on a non-plp column!"); - // Must be sequential reading - Debug.Assert(IsCommandBehavior(CommandBehavior.SequentialAccess), "GetCharsFromPlpData called for non-Sequential access"); +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); - if (!_metaData[i].metaType.IsCharType) + RuntimeHelpers.PrepareConstrainedRegions(); + try { - throw SQL.NonCharColumn(_metaData[i].column); - } - - if (_sharedState._nextColumnHeaderToRead <= i) + tdsReliabilitySection.Start(); +#else { - ReadColumnHeader(i); - } +#endif + long cch; - // If data is null, ReadColumnHeader sets the data.IsNull bit. - if (_data[i] != null && _data[i].IsNull) - { - throw new SqlNullValueException(); - } + AssertReaderState(requireData: true, permitAsync: false, columnIndex: i, enforceSequentialAccess: true); + Debug.Assert(!HasActiveStreamOrTextReaderOnColumn(i), "Column has active Stream or TextReader"); + // don't allow get bytes on non-long or non-binary columns + Debug.Assert(_metaData[i].metaType.IsPlp, "GetCharsFromPlpData called on a non-plp column!"); + // Must be sequential reading + Debug.Assert(IsCommandBehavior(CommandBehavior.SequentialAccess), "GetCharsFromPlpData called for non-Sequential access"); - if (dataIndex < _columnDataCharsRead) - { - // Don't allow re-read of same chars in sequential access mode - throw ADP.NonSeqByteAccess(dataIndex, _columnDataCharsRead, nameof(GetChars)); - } + if (!_metaData[i].metaType.IsCharType) + { + throw SQL.NonCharColumn(_metaData[i].column); + } - // If we start reading the new column, either dataIndex is 0 or - // _columnDataCharsRead is 0 and dataIndex > _columnDataCharsRead is true below. - // In both cases we will clean decoder - if (dataIndex == 0) - { - _stateObj._plpdecoder = null; - } + if (_sharedState._nextColumnHeaderToRead <= i) + { + ReadColumnHeader(i); + } - bool isUnicode = _metaData[i].metaType.IsNCharType; + // If data is null, ReadColumnHeader sets the data.IsNull bit. + if (_data[i] != null && _data[i].IsNull) + { + throw new SqlNullValueException(); + } - // If there are an unknown (-1) number of bytes left for a PLP, read its size - if (-1 == _sharedState._columnDataBytesRemaining) - { - _sharedState._columnDataBytesRemaining = (long)_parser.PlpBytesLeft(_stateObj); - } + if (dataIndex < _columnDataCharsRead) + { + // Don't allow re-read of same chars in sequential access mode + throw ADP.NonSeqByteAccess(dataIndex, _columnDataCharsRead, nameof(GetChars)); + } - if (0 == _sharedState._columnDataBytesRemaining) - { - _stateObj._plpdecoder = null; - return 0; // We've read this column to the end - } + // If we start reading the new column, either dataIndex is 0 or + // _columnDataCharsRead is 0 and dataIndex > _columnDataCharsRead is true below. + // In both cases we will clean decoder + if (dataIndex == 0) + { + _stateObj._plpdecoder = null; + } - // if no buffer is passed in, return the total number of characters or -1 - if (buffer == null) - { - cch = (long)_parser.PlpBytesTotalLength(_stateObj); - return (isUnicode && (cch > 0)) ? cch >> 1 : cch; - } - if (dataIndex > _columnDataCharsRead) - { - // Skip chars + bool isUnicode = _metaData[i].metaType.IsNCharType; - // Clean decoder state: we do not reset it, but destroy to ensure - // that we do not start decoding the column with decoder from the old one - _stateObj._plpdecoder = null; - cch = dataIndex - _columnDataCharsRead; - cch = isUnicode ? (cch << 1) : cch; - cch = (long)_parser.SkipPlpValue((ulong)(cch), _stateObj); - _columnDataBytesRead += cch; - _columnDataCharsRead += (isUnicode && (cch > 0)) ? cch >> 1 : cch; - } - cch = length; + // If there are an unknown (-1) number of bytes left for a PLP, read its size + if (-1 == _sharedState._columnDataBytesRemaining) + { + _sharedState._columnDataBytesRemaining = (long)_parser.PlpBytesLeft(_stateObj); + } - if (isUnicode) - { - cch = (long)_parser.ReadPlpUnicodeChars(ref buffer, bufferIndex, length, _stateObj); - _columnDataBytesRead += (cch << 1); + if (0 == _sharedState._columnDataBytesRemaining) + { + _stateObj._plpdecoder = null; + return 0; // We've read this column to the end + } + + // if no buffer is passed in, return the total number of characters or -1 + if (buffer == null) + { + cch = (long)_parser.PlpBytesTotalLength(_stateObj); + return (isUnicode && (cch > 0)) ? cch >> 1 : cch; + } + if (dataIndex > _columnDataCharsRead) + { + // Skip chars + + // Clean decoder state: we do not reset it, but destroy to ensure + // that we do not start decoding the column with decoder from the old one + _stateObj._plpdecoder = null; + cch = dataIndex - _columnDataCharsRead; + cch = isUnicode ? (cch << 1) : cch; + cch = (long)_parser.SkipPlpValue((ulong)(cch), _stateObj); + _columnDataBytesRead += cch; + _columnDataCharsRead += (isUnicode && (cch > 0)) ? cch >> 1 : cch; + } + cch = length; + + if (isUnicode) + { + cch = (long)_parser.ReadPlpUnicodeChars(ref buffer, bufferIndex, length, _stateObj); + _columnDataBytesRead += (cch << 1); + } + else + { + cch = (long)_parser.ReadPlpAnsiChars(ref buffer, bufferIndex, length, _metaData[i], _stateObj); + _columnDataBytesRead += cch << 1; + } + _columnDataCharsRead += cch; + _sharedState._columnDataBytesRemaining = (long)_parser.PlpBytesLeft(_stateObj); + return cch; } - else +#if NETFRAMEWORK && DEBUG + finally { - cch = (long)_parser.ReadPlpAnsiChars(ref buffer, bufferIndex, length, _metaData[i], _stateObj); - _columnDataBytesRead += cch << 1; + tdsReliabilitySection.Stop(); } - _columnDataCharsRead += cch; - _sharedState._columnDataBytesRemaining = (long)_parser.PlpBytesLeft(_stateObj); - return cch; +#endif } internal long GetStreamingXmlChars(int i, long dataIndex, char[] buffer, int bufferIndex, int length) @@ -3422,140 +3561,161 @@ private TdsOperationStatus TryNextResult(out bool more) SqlStatistics statistics = null; using (TryEventScope.Create("SqlDataReader.NextResult | API | Object Id {0}", ObjectID)) { +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif + try { - statistics = SqlStatistics.StartTimer(Statistics); +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); - SetTimeout(_defaultTimeoutMilliseconds); - - if (IsClosed) + RuntimeHelpers.PrepareConstrainedRegions(); + try { - throw ADP.DataReaderClosed(nameof(NextResult)); - } - _fieldNameLookup = null; + tdsReliabilitySection.Start(); +#else + { +#endif + statistics = SqlStatistics.StartTimer(Statistics); - bool success = false; // WebData 100390 - _hasRows = false; // reset HasRows + SetTimeout(_defaultTimeoutMilliseconds); - // if we are specifically only processing a single result, then read all the results off the wire and detach - if (IsCommandBehavior(CommandBehavior.SingleResult)) - { - result = TryCloseInternal(closeReader: false); - if (result != TdsOperationStatus.Done) + if (IsClosed) { - more = false; - return result; + throw ADP.DataReaderClosed(nameof(NextResult)); } + _fieldNameLookup = null; - // In the case of not closing the reader, null out the metadata AFTER - // CloseInternal finishes - since CloseInternal may go to the wire - // and use the metadata. - ClearMetaData(); - more = success; - return TdsOperationStatus.Done; - } + bool success = false; // WebData 100390 + _hasRows = false; // reset HasRows - if (_parser != null) - { - // if there are more rows, then skip them, the user wants the next result - bool moreRows = true; - while (moreRows) + // if we are specifically only processing a single result, then read all the results off the wire and detach + if (IsCommandBehavior(CommandBehavior.SingleResult)) { - result = TryReadInternal(false, out moreRows); + result = TryCloseInternal(closeReader: false); if (result != TdsOperationStatus.Done) { - // don't reset set the timeout value more = false; return result; } - } - } - // we may be done, so continue only if we have not detached ourselves from the parser - if (_parser != null) - { - bool moreResults; - result = TryHasMoreResults(out moreResults); - if (result != TdsOperationStatus.Done) - { - more = false; - return result; + // In the case of not closing the reader, null out the metadata AFTER + // CloseInternal finishes - since CloseInternal may go to the wire + // and use the metadata. + ClearMetaData(); + more = success; + return TdsOperationStatus.Done; } - if (moreResults) - { - _metaDataConsumed = false; - _browseModeInfoConsumed = false; - switch (_altRowStatus) + if (_parser != null) + { + // if there are more rows, then skip them, the user wants the next result + bool moreRows = true; + while (moreRows) { - case ALTROWSTATUS.AltRow: - int altRowId; - result = _parser.TryGetAltRowId(_stateObj, out altRowId); - if (result != TdsOperationStatus.Done) - { - more = false; - return result; - } - _SqlMetaDataSet altMetaDataSet = _altMetaDataSetCollection.GetAltMetaData(altRowId); - if (altMetaDataSet != null) - { - _metaData = altMetaDataSet; - } - Debug.Assert((_metaData != null), "Can't match up altrowmetadata"); - break; - case ALTROWSTATUS.Done: - // restore the row-metaData - _metaData = _altMetaDataSetCollection.metaDataSet; - Debug.Assert(_altRowStatus == ALTROWSTATUS.Done, "invalid AltRowStatus"); - _altRowStatus = ALTROWSTATUS.Null; - break; - default: - result = TryConsumeMetaData(); - if (result != TdsOperationStatus.Done) - { - more = false; - return result; - } - if (_metaData == null) - { - more = false; - return TdsOperationStatus.Done; - } - break; + result = TryReadInternal(false, out moreRows); + if (result != TdsOperationStatus.Done) + { + // don't reset set the timeout value + more = false; + return result; + } } - - success = true; } - else + + // we may be done, so continue only if we have not detached ourselves from the parser + if (_parser != null) { - // detach the parser from this reader now - result = TryCloseInternal(closeReader: false); + bool moreResults; + result = TryHasMoreResults(out moreResults); if (result != TdsOperationStatus.Done) { more = false; - return TdsOperationStatus.Done; + return result; } + if (moreResults) + { + _metaDataConsumed = false; + _browseModeInfoConsumed = false; - // In the case of not closing the reader, null out the metadata AFTER - // CloseInternal finishes - since CloseInternal may go to the wire - // and use the metadata. - result = TrySetMetaData(null, false); - if (result != TdsOperationStatus.Done) + switch (_altRowStatus) + { + case ALTROWSTATUS.AltRow: + int altRowId; + result = _parser.TryGetAltRowId(_stateObj, out altRowId); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } + _SqlMetaDataSet altMetaDataSet = _altMetaDataSetCollection.GetAltMetaData(altRowId); + if (altMetaDataSet != null) + { + _metaData = altMetaDataSet; + } + Debug.Assert((_metaData != null), "Can't match up altrowmetadata"); + break; + case ALTROWSTATUS.Done: + // restore the row-metaData + _metaData = _altMetaDataSetCollection.metaDataSet; + Debug.Assert(_altRowStatus == ALTROWSTATUS.Done, "invalid AltRowStatus"); + _altRowStatus = ALTROWSTATUS.Null; + break; + default: + result = TryConsumeMetaData(); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } + if (_metaData == null) + { + more = false; + return TdsOperationStatus.Done; + } + break; + } + + success = true; + } + else { - more = false; - return result; + // detach the parser from this reader now + result = TryCloseInternal(closeReader: false); + if (result != TdsOperationStatus.Done) + { + more = false; + return TdsOperationStatus.Done; + } + + // In the case of not closing the reader, null out the metadata AFTER + // CloseInternal finishes - since CloseInternal may go to the wire + // and use the metadata. + result = TrySetMetaData(null, false); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } } } + else + { + // Clear state in case of Read calling CloseInternal() then user calls NextResult() + // and the case where the Read() above will do essentially the same thing. + ClearMetaData(); + } + + more = success; + return TdsOperationStatus.Done; } - else +#if NETFRAMEWORK && DEBUG + finally { - // Clear state in case of Read calling CloseInternal() then user calls NextResult() - // and the case where the Read() above will do essentially the same thing. - ClearMetaData(); + tdsReliabilitySection.Stop(); } - - more = success; - return TdsOperationStatus.Done; +#endif } finally { @@ -3597,117 +3757,140 @@ private TdsOperationStatus TryReadInternal(bool setTimeout, out bool more) try { - TdsOperationStatus result; - statistics = SqlStatistics.StartTimer(Statistics); +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); - if (_parser != null) + RuntimeHelpers.PrepareConstrainedRegions(); + try { - if (setTimeout) - { - SetTimeout(_defaultTimeoutMilliseconds); - } - if (_sharedState._dataReady) + tdsReliabilitySection.Start(); +#else + { +#endif + TdsOperationStatus result; + statistics = SqlStatistics.StartTimer(Statistics); + + if (_parser != null) { - result = TryCleanPartialRead(); - if (result != TdsOperationStatus.Done) + if (setTimeout) { - more = false; - return result; + SetTimeout(_defaultTimeoutMilliseconds); + } + if (_sharedState._dataReady) + { + result = TryCleanPartialRead(); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } } - } - // clear out our buffers - SqlBuffer.Clear(_data); + // clear out our buffers + SqlBuffer.Clear(_data); - _sharedState._nextColumnHeaderToRead = 0; - _sharedState._nextColumnDataToRead = 0; - _sharedState._columnDataBytesRemaining = -1; // unknown - _lastColumnWithDataChunkRead = -1; + _sharedState._nextColumnHeaderToRead = 0; + _sharedState._nextColumnDataToRead = 0; + _sharedState._columnDataBytesRemaining = -1; // unknown + _lastColumnWithDataChunkRead = -1; - if (!_haltRead) - { - bool moreRows; - result = TryHasMoreRows(out moreRows); - if (result != TdsOperationStatus.Done) - { - more = false; - return result; - } - if (moreRows) + if (!_haltRead) { - // read the row from the backend (unless it's an altrow were the marker is already inside the altrow ...) - while (_stateObj.HasPendingData) + bool moreRows; + result = TryHasMoreRows(out moreRows); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } + if (moreRows) { - if (_altRowStatus != ALTROWSTATUS.AltRow) + // read the row from the backend (unless it's an altrow were the marker is already inside the altrow ...) + while (_stateObj.HasPendingData) { - // if this is an ordinary row we let the run method consume the ROW token - result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady); - if (result != TdsOperationStatus.Done) + if (_altRowStatus != ALTROWSTATUS.AltRow) { - more = false; - return result; + // if this is an ordinary row we let the run method consume the ROW token + result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } + if (_sharedState._dataReady) + { + break; + } } - if (_sharedState._dataReady) + else { + // ALTROW token and AltrowId are already consumed ... + Debug.Assert(_altRowStatus == ALTROWSTATUS.AltRow, "invalid AltRowStatus"); + _altRowStatus = ALTROWSTATUS.Done; + _sharedState._dataReady = true; break; } } - else + if (_sharedState._dataReady) { - // ALTROW token and AltrowId are already consumed ... - Debug.Assert(_altRowStatus == ALTROWSTATUS.AltRow, "invalid AltRowStatus"); - _altRowStatus = ALTROWSTATUS.Done; - _sharedState._dataReady = true; - break; + _haltRead = IsCommandBehavior(CommandBehavior.SingleRow); + more = true; + return TdsOperationStatus.Done; } } - if (_sharedState._dataReady) + + if (!_stateObj.HasPendingData) { - _haltRead = IsCommandBehavior(CommandBehavior.SingleRow); - more = true; - return TdsOperationStatus.Done; + result = TryCloseInternal(closeReader: false); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } } } - - if (!_stateObj.HasPendingData) + else { - result = TryCloseInternal(closeReader: false); + // if we did not get a row and halt is true, clean off rows of result + // success must be false - or else we could have just read off row and set + // halt to true + bool moreRows; + result = TryHasMoreRows(out moreRows); if (result != TdsOperationStatus.Done) { more = false; return result; } - } - } - else - { - // if we did not get a row and halt is true, clean off rows of result - // success must be false - or else we could have just read off row and set - // halt to true - bool moreRows; - result = TryHasMoreRows(out moreRows); - if (result != TdsOperationStatus.Done) - { - more = false; - return result; - } - while (moreRows) - { - // if we are in SingleRow mode, and we've read the first row, - // read the rest of the rows, if any - while (_stateObj.HasPendingData && !_sharedState._dataReady) + while (moreRows) { - result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady); - if (result != TdsOperationStatus.Done) + // if we are in SingleRow mode, and we've read the first row, + // read the rest of the rows, if any + while (_stateObj.HasPendingData && !_sharedState._dataReady) { - more = false; - return result; + result = _parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } } - } - if (_sharedState._dataReady) - { - result = TryCleanPartialRead(); + if (_sharedState._dataReady) + { + result = TryCleanPartialRead(); + if (result != TdsOperationStatus.Done) + { + more = false; + return result; + } + } + + // clear out our buffers + SqlBuffer.Clear(_data); + + _sharedState._nextColumnHeaderToRead = 0; + + result = TryHasMoreRows(out moreRows); if (result != TdsOperationStatus.Done) { more = false; @@ -3715,44 +3898,38 @@ private TdsOperationStatus TryReadInternal(bool setTimeout, out bool more) } } - // clear out our buffers - SqlBuffer.Clear(_data); - - _sharedState._nextColumnHeaderToRead = 0; - - result = TryHasMoreRows(out moreRows); - if (result != TdsOperationStatus.Done) - { - more = false; - return result; - } + // reset haltRead + _haltRead = false; } - - // reset haltRead - _haltRead = false; } - } - else if (IsClosed) - { - throw ADP.DataReaderClosed(nameof(Read)); - } - more = false; + else if (IsClosed) + { + throw ADP.DataReaderClosed(nameof(Read)); + } + more = false; #if DEBUG - if ((!_sharedState._dataReady) && (_stateObj.HasPendingData)) - { - byte token; - result = _stateObj.TryPeekByte(out token); - if (result != TdsOperationStatus.Done) + if ((!_sharedState._dataReady) && (_stateObj.HasPendingData)) { - return result; - } + byte token; + result = _stateObj.TryPeekByte(out token); + if (result != TdsOperationStatus.Done) + { + return result; + } - Debug.Assert(TdsParser.IsValidTdsToken(token), $"DataReady is false, but next token is invalid: {token,-2:X2}"); - } + Debug.Assert(TdsParser.IsValidTdsToken(token), $"DataReady is false, but next token is invalid: {token,-2:X2}"); + } #endif - return TdsOperationStatus.Done; + return TdsOperationStatus.Done; + } +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); + } +#endif //DEBUG } catch (OutOfMemoryException e) { @@ -3812,22 +3989,41 @@ private void ReadColumn(int i, bool setTimeout = true, bool allowPartiallyReadCo private TdsOperationStatus TryReadColumn(int i, bool setTimeout, bool allowPartiallyReadColumn = false, bool forStreaming = false) { CheckDataIsReady(columnIndex: i, permitAsync: true, allowPartiallyReadColumn: allowPartiallyReadColumn, methodName: null); +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); - Debug.Assert(_sharedState._nextColumnHeaderToRead <= _metaData.Length, "_sharedState._nextColumnHeaderToRead too large"); - Debug.Assert(_sharedState._nextColumnDataToRead <= _metaData.Length, "_sharedState._nextColumnDataToRead too large"); - - if (setTimeout) + RuntimeHelpers.PrepareConstrainedRegions(); + try { - SetTimeout(_defaultTimeoutMilliseconds); - } - - TdsOperationStatus result = TryReadColumnInternal(i, readHeaderOnly: false, forStreaming: forStreaming); - if (result != TdsOperationStatus.Done) + tdsReliabilitySection.Start(); +#else { - return result; +#endif + Debug.Assert(_sharedState._nextColumnHeaderToRead <= _metaData.Length, "_sharedState._nextColumnHeaderToRead too large"); + Debug.Assert(_sharedState._nextColumnDataToRead <= _metaData.Length, "_sharedState._nextColumnDataToRead too large"); + + if (setTimeout) + { + SetTimeout(_defaultTimeoutMilliseconds); + } + + TdsOperationStatus result = TryReadColumnInternal(i, readHeaderOnly: false, forStreaming: forStreaming); + if (result != TdsOperationStatus.Done) + { + return result; + } + + Debug.Assert(_data[i] != null, " data buffer is null?"); + } +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); } - - Debug.Assert(_data[i] != null, " data buffer is null?"); +#endif return TdsOperationStatus.Done; } @@ -3870,7 +4066,28 @@ private TdsOperationStatus TryReadColumnHeader(int i) { throw SQL.InvalidRead(); } - return TryReadColumnInternal(i, readHeaderOnly: true); + +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif +#if NETFRAMEWORK && DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + tdsReliabilitySection.Start(); +#else + { +#endif + return TryReadColumnInternal(i, readHeaderOnly: true); + } +#if NETFRAMEWORK && DEBUG + finally + { + tdsReliabilitySection.Stop(); + } +#endif } internal TdsOperationStatus TryReadColumnInternal(int i, bool readHeaderOnly = false, bool forStreaming = false) @@ -5342,7 +5559,23 @@ private static Task GetFieldValueAsyncExecute(Task task, object state) if (reader.IsCommandBehavior(CommandBehavior.SequentialAccess) && reader._sharedState._dataReady) { bool internalReadSuccess = false; - internalReadSuccess = reader.TryReadColumnInternal(context._columnIndex, readHeaderOnly: true) == TdsOperationStatus.Done; +#if NETFRAMEWORK + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + tdsReliabilitySection.Start(); +#else + { +#endif + internalReadSuccess = reader.TryReadColumnInternal(context._columnIndex, readHeaderOnly: true) == TdsOperationStatus.Done; + } +#if NETFRAMEWORK + finally + { + tdsReliabilitySection.Stop(); + } +#endif if (internalReadSuccess) { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs index 9eab4ae44f..4f655dc403 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs @@ -22,8 +22,8 @@ private struct RuntimeHelpers /// This is a no-op in netcore version. Only needed for merging with netfx codebase. /// [Conditional("NETFRAMEWORK")] - internal static void PrepareConstrainedRegions() - { + internal static void PrepareConstrainedRegions() + { } } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index 0ee952026a..b3cf628594 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -18,7 +18,7 @@ namespace Microsoft.Data.SqlClient using PacketHandle = IntPtr; using RuntimeHelpers = System.Runtime.CompilerServices.RuntimeHelpers; #endif - + sealed internal class LastIOTimer { internal long _value;