Skip to content

Commit ce5a1f7

Browse files
Fix bug with LegacyRowVersionNullBehavior (#1182)
1 parent ffce6d3 commit ce5a1f7

File tree

5 files changed

+160
-206
lines changed

5 files changed

+160
-206
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs

+12-20
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ protected override void Dispose(bool disposing)
842842
}
843843
base.Dispose(disposing);
844844
}
845-
catch(SqlException ex)
845+
catch (SqlException ex)
846846
{
847847
SqlClientEventSource.Log.TryTraceEvent("SqlDataReader.Dispose | ERR | Error Message: {0}, Stack Trace: {1}", ex.Message, ex.StackTrace);
848848
}
@@ -3771,26 +3771,18 @@ private bool TryReadColumnInternal(int i, bool readHeaderOnly = false)
37713771
_sharedState._nextColumnDataToRead = _sharedState._nextColumnHeaderToRead;
37723772
_sharedState._nextColumnHeaderToRead++; // We read this one
37733773

3774-
if (isNull)
3774+
// Trigger new behavior for RowVersion to send DBNull.Value by allowing entry for Timestamp or discard entry for Timestamp for legacy support.
3775+
// if LegacyRowVersionNullBehavior is enabled, Timestamp type must enter "else" block.
3776+
if (isNull && (!LocalAppContextSwitches.LegacyRowVersionNullBehavior || columnMetaData.type != SqlDbType.Timestamp))
37753777
{
3776-
if (columnMetaData.type == SqlDbType.Timestamp)
3777-
{
3778-
if (!LocalAppContextSwitches.LegacyRowVersionNullBehavior)
3779-
{
3780-
_data[i].SetToNullOfType(SqlBuffer.StorageType.SqlBinary);
3781-
}
3782-
}
3783-
else
3784-
{
3785-
TdsParser.GetNullSqlValue(_data[_sharedState._nextColumnDataToRead],
3778+
TdsParser.GetNullSqlValue(_data[_sharedState._nextColumnDataToRead],
37863779
columnMetaData,
37873780
_command != null ? _command.ColumnEncryptionSetting : SqlCommandColumnEncryptionSetting.UseConnectionSetting,
37883781
_parser.Connection);
37893782

3790-
if (!readHeaderOnly)
3791-
{
3792-
_sharedState._nextColumnDataToRead++;
3793-
}
3783+
if (!readHeaderOnly)
3784+
{
3785+
_sharedState._nextColumnDataToRead++;
37943786
}
37953787
}
37963788
else
@@ -4102,8 +4094,8 @@ internal bool TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo)
41024094

41034095
if (_parser != null)
41044096
{ // There is a valid case where parser is null
4105-
// Peek, and if row token present, set _hasRows true since there is a
4106-
// row in the result
4097+
// Peek, and if row token present, set _hasRows true since there is a
4098+
// row in the result
41074099
byte b;
41084100
if (!_stateObj.TryPeekByte(out b))
41094101
{
@@ -5015,7 +5007,7 @@ override public Task<T> GetFieldValueAsync<T>(int i, CancellationToken cancellat
50155007
{
50165008
_stateObj._shouldHaveEnoughData = true;
50175009
#endif
5018-
return Task.FromResult(GetFieldValueInternal<T>(i));
5010+
return Task.FromResult(GetFieldValueInternal<T>(i));
50195011
#if DEBUG
50205012
}
50215013
finally
@@ -5109,7 +5101,7 @@ internal void CompletePendingReadWithFailure(int errorCode, bool resetForcePendi
51095101

51105102
#endif
51115103

5112-
internal abstract class SqlDataReaderAsyncCallContext<T> : AAsyncCallContext<SqlDataReader,T>
5104+
internal abstract class SqlDataReaderAsyncCallContext<T> : AAsyncCallContext<SqlDataReader, T>
51135105
{
51145106
internal static readonly Action<Task<T>, object> s_completeCallback = CompleteAsyncCallCallback;
51155107

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs

+4
Original file line numberDiff line numberDiff line change
@@ -5424,6 +5424,10 @@ internal static object GetNullSqlValue(SqlBuffer nullVal, SqlMetaDataPriv md, Sq
54245424
break;
54255425

54265426
case SqlDbType.Timestamp:
5427+
if (!LocalAppContextSwitches.LegacyRowVersionNullBehavior)
5428+
{
5429+
nullVal.SetToNullOfType(SqlBuffer.StorageType.SqlBinary);
5430+
}
54275431
break;
54285432

54295433
default:

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDataReader.cs

+7-15
Original file line numberDiff line numberDiff line change
@@ -4281,26 +4281,18 @@ private bool TryReadColumnInternal(int i, bool readHeaderOnly = false)
42814281
_sharedState._nextColumnDataToRead = _sharedState._nextColumnHeaderToRead;
42824282
_sharedState._nextColumnHeaderToRead++; // We read this one
42834283

4284-
if (isNull)
4284+
// Trigger new behavior for RowVersion to send DBNull.Value by allowing entry for Timestamp or discard entry for Timestamp for legacy support.
4285+
// if LegacyRowVersionNullBehavior is enabled, Timestamp type must enter "else" block.
4286+
if (isNull && (!LocalAppContextSwitches.LegacyRowVersionNullBehavior || columnMetaData.type != SqlDbType.Timestamp))
42854287
{
4286-
if (columnMetaData.type == SqlDbType.Timestamp)
4287-
{
4288-
if (!LocalAppContextSwitches.LegacyRowVersionNullBehavior)
4289-
{
4290-
_data[i].SetToNullOfType(SqlBuffer.StorageType.SqlBinary);
4291-
}
4292-
}
4293-
else
4294-
{
4295-
TdsParser.GetNullSqlValue(_data[_sharedState._nextColumnDataToRead],
4288+
TdsParser.GetNullSqlValue(_data[_sharedState._nextColumnDataToRead],
42964289
columnMetaData,
42974290
_command != null ? _command.ColumnEncryptionSetting : SqlCommandColumnEncryptionSetting.UseConnectionSetting,
42984291
_parser.Connection);
42994292

4300-
if (!readHeaderOnly)
4301-
{
4302-
_sharedState._nextColumnDataToRead++;
4303-
}
4293+
if (!readHeaderOnly)
4294+
{
4295+
_sharedState._nextColumnDataToRead++;
43044296
}
43054297
}
43064298
else

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -6208,8 +6208,10 @@ internal static object GetNullSqlValue(
62086208
break;
62096209

62106210
case SqlDbType.Timestamp:
6211-
// Dev10 Bug #479607 - this should have been the same as SqlDbType.Binary, but it's a rejected breaking change
6212-
// Dev10 Bug #752790 - don't assert when it does happen
6211+
if (!LocalAppContextSwitches.LegacyRowVersionNullBehavior)
6212+
{
6213+
nullVal.SetToNullOfType(SqlBuffer.StorageType.SqlBinary);
6214+
}
62136215
break;
62146216

62156217
default:

0 commit comments

Comments
 (0)