diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
index 3872b215ae..ed2c4aedf7 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
@@ -8,15 +8,23 @@ namespace Microsoft.Data.SqlClient
{
internal static partial class LocalAppContextSwitches
{
+ private enum Tristate : byte
+ {
+ NotInitialized = 0,
+ False = 1,
+ True = 2
+ }
+
internal const string MakeReadAsyncBlockingString = @"Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking";
internal const string LegacyRowVersionNullString = @"Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior";
internal const string SuppressInsecureTLSWarningString = @"Switch.Microsoft.Data.SqlClient.SuppressInsecureTLSWarning";
internal const string UseMinimumLoginTimeoutString = @"Switch.Microsoft.Data.SqlClient.UseOneSecFloorInTimeoutCalculationDuringLogin";
- private static bool? s_legacyRowVersionNullBehavior;
- private static bool? s_suppressInsecureTLSWarning;
- private static bool s_makeReadAsyncBlocking;
- private static bool s_useMinimumLoginTimeout;
+ // this field is accessed through reflection in tests and should not be renamed or have the type changed without refactoring NullRow related tests
+ private static Tristate s_legacyRowVersionNullBehavior;
+ private static Tristate s_suppressInsecureTLSWarning;
+ private static Tristate s_makeReadAsyncBlocking;
+ private static Tristate s_useMinimumLoginTimeout;
#if !NETFRAMEWORK
static LocalAppContextSwitches()
@@ -36,7 +44,7 @@ static LocalAppContextSwitches()
#if NETFRAMEWORK
internal const string DisableTNIRByDefaultString = @"Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString";
- private static bool s_disableTNIRByDefault;
+ private static Tristate s_disableTNIRByDefault;
///
/// Transparent Network IP Resolution (TNIR) is a revision of the existing MultiSubnetFailover feature.
@@ -54,7 +62,23 @@ static LocalAppContextSwitches()
/// This app context switch defaults to 'false'.
///
public static bool DisableTNIRByDefault
- => AppContext.TryGetSwitch(DisableTNIRByDefaultString, out s_disableTNIRByDefault) && s_disableTNIRByDefault;
+ {
+ get
+ {
+ if (s_disableTNIRByDefault == Tristate.NotInitialized)
+ {
+ if (AppContext.TryGetSwitch(DisableTNIRByDefaultString, out bool returnedValue) && returnedValue)
+ {
+ s_disableTNIRByDefault = Tristate.True;
+ }
+ else
+ {
+ s_disableTNIRByDefault = Tristate.False;
+ }
+ }
+ return s_disableTNIRByDefault == Tristate.True;
+ }
+ }
#endif
///
@@ -66,13 +90,18 @@ public static bool SuppressInsecureTLSWarning
{
get
{
- if (s_suppressInsecureTLSWarning is null)
+ if (s_suppressInsecureTLSWarning == Tristate.NotInitialized)
{
- bool result;
- result = AppContext.TryGetSwitch(SuppressInsecureTLSWarningString, out result) && result;
- s_suppressInsecureTLSWarning = result;
+ if (AppContext.TryGetSwitch(SuppressInsecureTLSWarningString, out bool returnedValue) && returnedValue)
+ {
+ s_suppressInsecureTLSWarning = Tristate.True;
+ }
+ else
+ {
+ s_suppressInsecureTLSWarning = Tristate.False;
+ }
}
- return s_suppressInsecureTLSWarning.Value;
+ return s_suppressInsecureTLSWarning == Tristate.True;
}
}
@@ -86,13 +115,18 @@ public static bool LegacyRowVersionNullBehavior
{
get
{
- if (s_legacyRowVersionNullBehavior is null)
+ if (s_legacyRowVersionNullBehavior == Tristate.NotInitialized)
{
- bool result;
- result = AppContext.TryGetSwitch(LegacyRowVersionNullString, out result) && result;
- s_legacyRowVersionNullBehavior = result;
+ if (AppContext.TryGetSwitch(LegacyRowVersionNullString, out bool returnedValue) && returnedValue)
+ {
+ s_legacyRowVersionNullBehavior = Tristate.True;
+ }
+ else
+ {
+ s_legacyRowVersionNullBehavior = Tristate.False;
+ }
}
- return s_legacyRowVersionNullBehavior.Value;
+ return s_legacyRowVersionNullBehavior == Tristate.True;
}
}
@@ -101,7 +135,23 @@ public static bool LegacyRowVersionNullBehavior
/// This app context switch defaults to 'false'.
///
public static bool MakeReadAsyncBlocking
- => AppContext.TryGetSwitch(MakeReadAsyncBlockingString, out s_makeReadAsyncBlocking) && s_makeReadAsyncBlocking;
+ {
+ get
+ {
+ if (s_makeReadAsyncBlocking == Tristate.NotInitialized)
+ {
+ if (AppContext.TryGetSwitch(MakeReadAsyncBlockingString, out bool returnedValue) && returnedValue)
+ {
+ s_makeReadAsyncBlocking = Tristate.True;
+ }
+ else
+ {
+ s_makeReadAsyncBlocking = Tristate.False;
+ }
+ }
+ return s_makeReadAsyncBlocking == Tristate.True;
+ }
+ }
///
/// Specifies minimum login timeout to be set to 1 second instead of 0 seconds,
@@ -109,6 +159,22 @@ public static bool MakeReadAsyncBlocking
/// This app context switch defaults to 'true'.
///
public static bool UseMinimumLoginTimeout
- => !AppContext.TryGetSwitch(UseMinimumLoginTimeoutString, out s_useMinimumLoginTimeout) || s_useMinimumLoginTimeout;
+ {
+ get
+ {
+ if (s_useMinimumLoginTimeout == Tristate.NotInitialized)
+ {
+ if (AppContext.TryGetSwitch(UseMinimumLoginTimeoutString, out bool returnedValue) && returnedValue)
+ {
+ s_useMinimumLoginTimeout = Tristate.True;
+ }
+ else
+ {
+ s_useMinimumLoginTimeout = Tristate.False;
+ }
+ }
+ return s_useMinimumLoginTimeout == Tristate.True;
+ }
+ }
}
}
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs
index 6929d35ee7..d00ea1d226 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs
@@ -17,6 +17,14 @@ public static class DataReaderTest
{
private static readonly object s_rowVersionLock = new();
+ // this enum must mirror the definition in LocalAppContextSwitches
+ private enum Tristate : byte
+ {
+ NotInitialized = 0,
+ False = 1,
+ True = 2
+ }
+
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
public static void LoadReaderIntoDataTableToTestGetSchemaTable()
{
@@ -261,7 +269,7 @@ public static void CheckNullRowVersionIsBDNull()
{
lock (s_rowVersionLock)
{
- bool? originalValue = SetLegacyRowVersionNullBehavior(false);
+ Tristate originalValue = SetLegacyRowVersionNullBehavior(Tristate.False);
try
{
using SqlConnection con = new(DataTestUtility.TCPConnectionString);
@@ -298,7 +306,7 @@ public static void CheckLegacyNullRowVersionIsEmptyArray()
{
lock (s_rowVersionLock)
{
- bool? originalValue = SetLegacyRowVersionNullBehavior(true);
+ Tristate originalValue = SetLegacyRowVersionNullBehavior(Tristate.True);
try
{
using SqlConnection con = new(DataTestUtility.TCPConnectionString);
@@ -323,11 +331,11 @@ public static void CheckLegacyNullRowVersionIsEmptyArray()
}
}
- private static bool? SetLegacyRowVersionNullBehavior(bool? value)
+ private static Tristate SetLegacyRowVersionNullBehavior(Tristate value)
{
Type switchesType = typeof(SqlCommand).Assembly.GetType("Microsoft.Data.SqlClient.LocalAppContextSwitches");
FieldInfo switchField = switchesType.GetField("s_legacyRowVersionNullBehavior", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
- bool? originalValue = (bool?)switchField.GetValue(null);
+ Tristate originalValue = (Tristate)switchField.GetValue(null);
switchField.SetValue(null, value);
return originalValue;
}