diff --git a/.github/instructions/features.instructions.md b/.github/instructions/features.instructions.md
index 34262b8db6..0fda359a15 100644
--- a/.github/instructions/features.instructions.md
+++ b/.github/instructions/features.instructions.md
@@ -243,6 +243,7 @@ AppContext switches allow runtime behavior changes without modifying connection
| Switch Name | Default | Description |
|-------------|---------|-------------|
| `Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString` | `false` | Disables Transparent Network IP Resolution by default |
+| `Switch.Microsoft.Data.SqlClient.EnableAppConfig` | `true` | Controls whether SqlClient reads app.config: configurable retry logic, authentication providers, switch overrides and, on .NET Framework, `system.data.localdb`. See [Trimming](#trimming) |
| `Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault` | `false` | Sets `MultiSubnetFailover=true` as the default for all connections |
| `Switch.Microsoft.Data.SqlClient.EnableUserAgent` | varies | Controls sending user agent information to SQL Server |
| `Switch.Microsoft.Data.SqlClient.IgnoreServerProvidedFailoverPartner` | `false` | Ignores failover partner information sent by the server |
@@ -273,6 +274,18 @@ AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverB
// }
```
+### Trimming
+
+`EnableAppConfig` removes the configuration reading from a trimmed or Native AOT application only when set at publish time:
+
+```xml
+
+
+
+```
+
+Setting it only at run time, with `AppContext.SetSwitch` or `runtimeconfig.json`, stops the reading but leaves the trim warnings.
+
### Guidelines for Adding New Switches
1. Define the switch name constant in `LocalAppContextSwitches.cs`
2. Add a cached property with lazy evaluation pattern (see existing switches)
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 06bf6c4f0e..9fd97a33f3 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
@@ -29,6 +29,13 @@ internal static class LocalAppContextSwitches
"Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString";
#endif
+ ///
+ /// The name of the app context switch that controls whether SqlClient
+ /// reads app.config.
+ ///
+ private const string EnableAppConfigString =
+ "Switch.Microsoft.Data.SqlClient.EnableAppConfig";
+
///
/// The name of the app context switch that controls whether
/// MultiSubnetFailover is enabled by default in the connection string.
@@ -186,6 +193,11 @@ private enum SwitchValue : byte
private static SwitchValue s_disableTnirByDefault = SwitchValue.None;
#endif
+ ///
+ /// The cached value of the EnableAppConfig switch.
+ ///
+ private static SwitchValue s_enableAppConfig = SwitchValue.None;
+
///
/// The cached value of the EnableMultiSubnetFailoverByDefault switch.
///
@@ -283,6 +295,13 @@ private enum SwitchValue : byte
///
static LocalAppContextSwitches()
{
+ // Read before any override is applied, so this switch itself cannot be
+ // set from the config file it gates.
+ if (!EnableAppConfig)
+ {
+ return;
+ }
+
IAppContextSwitchOverridesSection appContextSwitch = AppConfigManager.FetchConfigurationSection(AppContextSwitchOverridesSection.Name);
try
@@ -329,6 +348,25 @@ static LocalAppContextSwitches()
ref s_disableTnirByDefault);
#endif
+ ///
+ /// When set to false, SqlClient does not read app.config. Configurable
+ /// retry logic, authentication providers and switch overrides are then not
+ /// taken from the configuration file.
+ ///
+ /// ILLink.Substitutions.xml allows the configuration reading, and the type
+ /// resolution it drives, to be trimmed away when the corresponding
+ /// AppContext switch is set at compile time. In such cases, this property
+ /// will return a constant value, even if the AppContext switch is set or
+ /// reset at runtime.
+ ///
+ /// The default value of this switch is true.
+ ///
+ public static bool EnableAppConfig =>
+ AcquireAndReturn(
+ EnableAppConfigString,
+ defaultValue: true,
+ ref s_enableAppConfig);
+
///
/// When set to true, the default value for MultiSubnetFailover connection
/// string property will be true instead of false. This enables parallel IP
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalDb/LocalDbApi.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalDb/LocalDbApi.cs
index da1e613c44..529952e8aa 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalDb/LocalDbApi.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalDb/LocalDbApi.cs
@@ -182,7 +182,9 @@ internal static void CreateLocalDbInstance(string instance)
{
Dictionary tempConfigurableInstances =
new Dictionary(StringComparer.OrdinalIgnoreCase);
- object section = ConfigurationManager.GetSection("system.data.localdb");
+ object section = LocalAppContextSwitches.EnableAppConfig
+ ? ConfigurationManager.GetSection("system.data.localdb")
+ : null;
if (section is not null)
{
// Validate section type
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs
index 082a5599ce..5a37060285 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs
@@ -40,12 +40,15 @@ static SqlAuthenticationProviderManager()
try
{
- // New configuration section "SqlClientAuthenticationProviders" for Microsoft.Data.SqlClient accepted to avoid conflicts with older one.
- configurationSection = FetchConfigurationSection(SqlClientAuthenticationProviderConfigurationSection.Name);
- if (configurationSection == null)
+ if (LocalAppContextSwitches.EnableAppConfig)
{
- // If configuration section is not yet found, try with old Configuration Section name for backwards compatibility
- configurationSection = FetchConfigurationSection(SqlAuthenticationProviderConfigurationSection.Name);
+ // New configuration section "SqlClientAuthenticationProviders" for Microsoft.Data.SqlClient accepted to avoid conflicts with older one.
+ configurationSection = FetchConfigurationSection(SqlClientAuthenticationProviderConfigurationSection.Name);
+ if (configurationSection == null)
+ {
+ // If configuration section is not yet found, try with old Configuration Section name for backwards compatibility
+ configurationSection = FetchConfigurationSection(SqlAuthenticationProviderConfigurationSection.Name);
+ }
}
}
catch (ConfigurationErrorsException e)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.cs
index c90ac4520d..f12ac8b49d 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.cs
@@ -166,6 +166,9 @@ public sealed partial class SqlCommand : DbCommand, ICloneable
///
private static readonly SqlDiagnosticListener s_diagnosticListener = new();
+ // Shared by all commands when app.config is not read.
+ private static SqlRetryLogicBaseProvider s_noneRetryProvider;
+
///
/// Connection that will be used to process the current instance.
///
@@ -763,7 +766,9 @@ public SqlRetryLogicBaseProvider RetryLogicProvider
{
get
{
- _retryLogicProvider ??= SqlConfigurableRetryLogicManager.CommandProvider;
+ _retryLogicProvider ??= LocalAppContextSwitches.EnableAppConfig
+ ? SqlConfigurableRetryLogicManager.CommandProvider
+ : LazyInitializer.EnsureInitialized(ref s_noneRetryProvider, SqlConfigurableRetryFactory.CreateNoneRetryProvider);
return _retryLogicProvider;
}
set => _retryLogicProvider = value;
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs
index 66b8df4564..f433e0c78f 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs
@@ -142,6 +142,9 @@ private static readonly ConcurrentDictionary> _ColumnEncry
private static readonly Action