Skip to content

Cleanup | Centralise AppContext switches #3492

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,11 @@

<Compile Include="Microsoft\Data\SqlClient\TdsParser.Windows.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParserStateObjectNative.cs" />

<EmbeddedResource Include="$(CommonSourceRoot)Resources\ILLink.Substitutions.Windows.xml">
<LogicalName>ILLink.Substitutions.xml</LogicalName>
<Link>Resources\ILLink.Substitutions.Windows.xml</Link>
</EmbeddedResource>
</ItemGroup>

<!-- Unix only -->
Expand Down Expand Up @@ -1005,6 +1010,11 @@
</Compile>

<Compile Include="Microsoft\Data\SqlClient\TdsParser.Unix.cs" />

<EmbeddedResource Include="$(CommonSourceRoot)Resources\ILLink.Substitutions.Unix.xml">
<LogicalName>ILLink.Substitutions.xml</LogicalName>
<Link>Resources\ILLink.Substitutions.Unix.xml</Link>
</EmbeddedResource>
</ItemGroup>

<!-- Resources -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ namespace Microsoft.Data.SqlClient
[DesignerCategory("")]
public sealed partial class SqlConnection : DbConnection, ICloneable
{
private enum CultureCheckState : uint
{
Unknown = 0,
Standard = 1,
Invariant = 2
}

private bool _AsyncCommandInProgress;

// SQLStatistics support
Expand Down Expand Up @@ -75,9 +68,6 @@ private enum CultureCheckState : uint
// using SqlConnection.Open() method.
internal bool _applyTransientFaultHandling = false;

// status of invariant culture environment check
private static CultureCheckState _cultureCheckState;

// System column encryption key store providers are added by default
private static readonly Dictionary<string, SqlColumnEncryptionKeyStoreProvider> s_systemColumnEncryptionKeyStoreProviders
= new(capacity: 3, comparer: StringComparer.OrdinalIgnoreCase)
Expand Down Expand Up @@ -1956,48 +1946,9 @@ private bool TryOpen(TaskCompletionSource<DbConnectionInternal> retry, SqlConnec
{
SqlConnectionString connectionOptions = (SqlConnectionString)ConnectionOptions;

if (_cultureCheckState != CultureCheckState.Standard)
if (LocalAppContextSwitches.GlobalizationInvariantMode)
{
// .NET Core 2.0 and up supports a Globalization Invariant Mode to reduce the size of
// required libraries for applications which don't need globalization support. SqlClient
// requires those libraries for core functionality and will throw exceptions later if they
// are not present. Throwing on open with a meaningful message helps identify the issue.
if (_cultureCheckState == CultureCheckState.Unknown)
{
// check if invariant state has been set by appcontext switch directly
if (AppContext.TryGetSwitch("System.Globalization.Invariant", out bool isEnabled) && isEnabled)
{
_cultureCheckState = CultureCheckState.Invariant;
}
else
{
// check if invariant state has been set through environment variables
string envValue = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT");
if (string.Equals(envValue, bool.TrueString, StringComparison.OrdinalIgnoreCase) || string.Equals(envValue, "1", StringComparison.OrdinalIgnoreCase))
{
_cultureCheckState = CultureCheckState.Invariant;
}
else
{
// if it hasn't been manually set it could still apply if the os doesn't have
// icu libs installed or is a native binary with icu support trimmed away
// netcore 3.1 to net5 do not throw in attempting to create en-us in inariant mode
// net6 and greater will throw so catch and infer invariant mode from the exception
try
{
_cultureCheckState = CultureInfo.GetCultureInfo("en-US").EnglishName.Contains("Invariant") ? CultureCheckState.Invariant : CultureCheckState.Standard;
}
catch (CultureNotFoundException)
{
_cultureCheckState = CultureCheckState.Invariant;
}
}
}
}
if (_cultureCheckState == CultureCheckState.Invariant)
{
throw SQL.GlobalizationInvariantModeNotSupported();
}
throw SQL.GlobalizationInvariantModeNotSupported();
}

_applyTransientFaultHandling = (!overrides.HasFlag(SqlConnectionOverrides.OpenWithoutRetry) && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal sealed partial class TdsParser
{
internal void PostReadAsyncForMars()
{
if (TdsParserStateObjectFactory.UseManagedSNI)
if (LocalAppContextSwitches.UseManagedNetworking)
return;

// HACK HACK HACK - for Async only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ internal sealed partial class TdsParser
// Constants
private const int constBinBufferSize = 4096; // Size of the buffer used to read input parameter of type Stream
private const int constTextBufferSize = 4096; // Size of the buffer (in chars) user to read input parameter of type TextReader
private const string enableTruncateSwitch = "Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal"; // for applications that need to maintain backwards compatibility with the previous behavior

// State variables
internal TdsParserState _state = TdsParserState.Closed; // status flag for connection
Expand Down Expand Up @@ -204,16 +203,6 @@ internal SqlInternalConnectionTds Connection
}
}

private static bool EnableTruncateSwitch
{
get
{
bool value;
value = AppContext.TryGetSwitch(enableTruncateSwitch, out value) ? value : false;
return value;
}
}

internal SqlInternalTransaction CurrentTransaction
{
get
Expand Down Expand Up @@ -631,7 +620,7 @@ internal void EnableMars()
// Cache physical stateObj and connection.
_pMarsPhysicalConObj = _physicalStateObj;

if (TdsParserStateObjectFactory.UseManagedSNI)
if (LocalAppContextSwitches.UseManagedNetworking)
_pMarsPhysicalConObj.IncrementPendingCallbacks();

uint info = 0;
Expand Down Expand Up @@ -1489,7 +1478,7 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj)
* !=null | == 0 | replace text left of errorMessage
*/

if (TdsParserStateObjectFactory.UseManagedSNI)
if (LocalAppContextSwitches.UseManagedNetworking)
{
Debug.Assert(!string.IsNullOrEmpty(details.ErrorMessage) || details.SniErrorNumber != 0, "Empty error message received from SNI");
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.TdsParser.ProcessSNIError |ERR|ADV > Empty error message received from SNI. Error Message = {0}, SNI Error Number ={1}", details.ErrorMessage, details.SniErrorNumber);
Expand Down Expand Up @@ -1538,7 +1527,7 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj)
}
else
{
if (TdsParserStateObjectFactory.UseManagedSNI)
if (LocalAppContextSwitches.UseManagedNetworking)
{
// SNI error. Append additional error message info if available and hasn't been included.
string sniLookupMessage = SQL.GetSNIErrorMessage(details.SniErrorNumber);
Expand Down Expand Up @@ -7653,7 +7642,7 @@ internal static SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale)
{
if (d.Scale != newScale)
{
bool round = !EnableTruncateSwitch;
bool round = !LocalAppContextSwitches.TruncateScaledDecimal;
return SqlDecimal.AdjustScale(d, newScale - d.Scale, round);
}

Expand All @@ -7666,7 +7655,7 @@ internal static decimal AdjustDecimalScale(decimal value, int newScale)

if (newScale != oldScale)
{
bool round = !EnableTruncateSwitch;
bool round = !LocalAppContextSwitches.TruncateScaledDecimal;
SqlDecimal num = new SqlDecimal(value);
num = SqlDecimal.AdjustScale(num, newScale - oldScale, round);
return num.Value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ internal sealed partial class TdsParser
// Constants
private const int constBinBufferSize = 4096; // Size of the buffer used to read input parameter of type Stream
private const int constTextBufferSize = 4096; // Size of the buffer (in chars) user to read input parameter of type TextReader
private const string enableTruncateSwitch = "Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal"; // for applications that need to maintain backwards compatibility with the previous behavior

// State variables
internal TdsParserState _state = TdsParserState.Closed; // status flag for connection
Expand Down Expand Up @@ -205,16 +204,6 @@ internal SqlInternalConnectionTds Connection
}
}

private static bool EnableTruncateSwitch
{
get
{
bool value;
value = AppContext.TryGetSwitch(enableTruncateSwitch, out value) ? value : false;
return value;
}
}

internal SqlInternalTransaction CurrentTransaction
{
get
Expand Down Expand Up @@ -7849,7 +7838,7 @@ internal static SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale)
{
if (d.Scale != newScale)
{
bool round = !EnableTruncateSwitch;
bool round = !LocalAppContextSwitches.TruncateScaledDecimal;
return SqlDecimal.AdjustScale(d, newScale - d.Scale, round);
}

Expand All @@ -7862,7 +7851,7 @@ internal static decimal AdjustDecimalScale(decimal value, int newScale)

if (newScale != oldScale)
{
bool round = !EnableTruncateSwitch;
bool round = !LocalAppContextSwitches.TruncateScaledDecimal;
SqlDecimal num = new SqlDecimal(value);
num = SqlDecimal.AdjustScale(num, newScale - oldScale, round);
return num.Value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ private partial DataTable GetDataSourcesInternal()
#if NETFRAMEWORK
return SqlDataSourceEnumeratorNativeHelper.GetDataSources();
#else
return SqlClient.TdsParserStateObjectFactory.UseManagedSNI ? SqlDataSourceEnumeratorManagedHelper.GetDataSources() : SqlDataSourceEnumeratorNativeHelper.GetDataSources();
return SqlClient.LocalAppContextSwitches.UseManagedNetworking ? SqlDataSourceEnumeratorManagedHelper.GetDataSources() : SqlDataSourceEnumeratorNativeHelper.GetDataSources();
#endif
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal static WindowsIdentity GetCurrentWindowsIdentity()
#else
internal static DbConnectionPoolIdentity GetCurrent()
{
return TdsParserStateObjectFactory.UseManagedSNI ? GetCurrentManaged() : GetCurrentNative();
return LocalAppContextSwitches.UseManagedNetworking ? GetCurrentManaged() : GetCurrentNative();
}
#endif

Expand Down
Loading
Loading