Add five missing SqlClient AppContext switches and a switch-latching note - #10381
Conversation
|
Learn Build status updates of commit b6094bb: ✅ Validation status: passed
For more details, please refer to the build report. |
|
@microsoft-github-policy-service agree |
|
Fede Paganini (@federico-paganini) : Thanks for your contribution! The author(s) and reviewer(s) have been notified to review your proposed change. |
|
Fede Paganini (@federico-paganini) : Thanks for your contribution! The author(s) and reviewer(s) have been notified to review your proposed change. |
There was a problem hiding this comment.
Pull request overview
Updates the SqlClient AppContext switches documentation to match current SqlClient behavior by documenting five additional switches and clarifying switch value “latching” semantics (cached on first consult).
Changes:
- Adds a cross-cutting note explaining that switch values are cached on first consult.
- Adds new sections documenting five previously missing SqlClient AppContext switches, including usage examples and version availability.
- Updates
ms.date.
Suppressed comments (2)
docs/connect/ado-net/appcontext-switches.md:247
- This section doesn't state the switch's default value, even though the PR description says each added section includes defaults. Consider adding that the default is
false(new behavior is on by default; switch opts back into legacy behavior).
Starting in version 7.1.0-preview2, when connecting with failover configured, SqlClient no longer alternates to the failover partner on login-phase SQL errors if the connection's parser state isn't closed. To revert to the legacy alternation behavior, enable the AppContext switch **Switch.Microsoft.Data.SqlClient.UseLegacyFailoverAlternationOnLoginSqlErrors** on application startup.
docs/connect/ado-net/appcontext-switches.md:257
- This section describes the legacy behavior but doesn't explicitly state the switch default value. Since this switch is inverted (set it to
falseto get the new behavior), adding the default (true) would reduce ambiguity.
By default, when a parameter's scale is explicitly set to zero for the vartime data types (`datetime2`, `datetimeoffset`, and `time`), SqlClient sends the default scale of 7 instead. Starting in version 6.0, you can disable the legacy behavior, so that an explicitly set zero scale is honored, by disabling the AppContext switch **Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviour** on application startup.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| The AppContext class allows SqlClient to provide new functionality while continuing to support callers who depend on the previous behavior. Users can opt out of a change in behavior by setting specific AppContext switches. | ||
|
|
||
| SqlClient reads each switch once and caches the value the first time the switch is consulted. Set switches at application startup, before the first use of any SqlClient type — a switch set later in the application's lifetime has no effect. |
|
|
||
| [!INCLUDE [dotnet-all](../../includes/products/applies-plain/dotnet-all.md)] | ||
|
|
||
| Starting in version 6.1, SqlClient includes a new connection pool implementation (V2). The V1 pool remains the default. To opt in to the V2 pool, enable the AppContext switch **Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2** on application startup. |
|
Both findings addressed in 8a33903: the latching note now says a switch takes effect only if set before SqlClient first consults that switch (startup remains the practical guidance, since first consultation isn't generally observable), and the three sections that didn't state their switch default now do ( |
|
Learn Build status updates of commit 8a33903: ✅ Validation status: passed
For more details, please refer to the build report. |
|
Can you review the proposed changes? Important: When the changes are ready for publication, adding a #label:"aq-pr-triaged" |
David Levy (dlevy-msft-sql)
left a comment
There was a problem hiding this comment.
Two technical corrections are required: describe idle-timeout eviction as best-effort rather than a hard maximum, and identify connection pool V2 as experimental. I also left focused wording suggestions to align the additions with the Microsoft Learn style guide and this repository's conventions. Apply the same formatting consistently throughout the new sections: use code formatting for literal switch names and “at application startup” for timing.
|
|
||
| [!INCLUDE [dotnet-all](../../includes/products/applies-plain/dotnet-all.md)] | ||
|
|
||
| By default, when a parameter's scale is explicitly set to zero for the vartime data types (`datetime2`, `datetimeoffset`, and `time`), SqlClient sends the default scale of 7 instead. Starting in version 6.0, you can disable the legacy behavior, so that an explicitly set zero scale is honored, by disabling the AppContext switch **Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviour** on application startup. The switch defaults to `true`. |
There was a problem hiding this comment.
Please align this paragraph with the Learn and repository style rules: format SQL Server data types in bold, format the literal switch name as code rather than bold, use “at application startup,” and remove the repeated “disable ... by disabling.” Suggested wording:
By default, SqlClient sends a scale of 7 when you explicitly set the scale to 0 for datetime2, datetimeoffset, or time parameters. With version 6.0 and later versions, set
Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviourtofalseat application startup to preserve the explicit scale of 0. The switch defaults totrue.
|
|
||
| [!INCLUDE [dotnet-all](../../includes/products/applies-plain/dotnet-all.md)] | ||
|
|
||
| Starting in version 6.1, SqlClient includes a new connection pool implementation (V2). The V1 pool remains the default (the switch defaults to `false`). To opt in to the V2 pool, enable the AppContext switch **Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2** on application startup. |
There was a problem hiding this comment.
P2: Please state that connection pool V2 is experimental. The SqlClient 7.1 preview release notes still identify it that way, but this paragraph presents it as a normal alternative. Suggested opening: “Starting in version 6.1, SqlClient includes an alternative, experimental connection pool implementation (V2).”
|
|
||
| [!INCLUDE [dotnet-all](../../includes/products/applies-plain/dotnet-all.md)] | ||
|
|
||
| Starting in version 7.1.0-preview2, when connecting with failover configured, SqlClient no longer alternates to the failover partner on login-phase SQL errors if the connection's parser state isn't closed. To revert to the legacy alternation behavior, enable the AppContext switch **Switch.Microsoft.Data.SqlClient.UseLegacyFailoverAlternationOnLoginSqlErrors** on application startup. The switch defaults to `false`. |
There was a problem hiding this comment.
Please format the literal switch name as code rather than bold and use “at application startup” rather than “on application startup.” Also consider replacing the implementation-oriented phrase “if the connection's parser state isn't closed” with user-facing wording, such as “for SQL errors returned during the login phase.”
|
|
||
| The AppContext class allows SqlClient to provide new functionality while continuing to support callers who depend on the previous behavior. Users can opt out of a change in behavior by setting specific AppContext switches. | ||
|
|
||
| SqlClient reads each switch once and caches the value the first time it consults that switch. Because it isn't generally observable when a given switch is first consulted, set switches at application startup, before the first use of any SqlClient type — a switch set after it has been consulted has no effect. |
There was a problem hiding this comment.
For shorter, more direct Learn-style wording, consider splitting this into three sentences:
SqlClient reads and caches each switch the first time it uses that switch. Set switches at application startup, before you use any SqlClient types. Changing a switch after SqlClient has cached its value has no effect.
|
|
||
| [!INCLUDE [dotnet-all](../../includes/products/applies-plain/dotnet-all.md)] | ||
|
|
||
| Starting in version 7.1.0-preview2, the `Connection Idle Timeout` connection string keyword configures the maximum time, in seconds, that a pooled connection can sit unused before the pool discards it (default 300; a value of 0 disables idle expiration). The keyword is only enforced when the legacy idle-timeout behavior is disabled. With the switch at its default value of `true`, the pool preserves the historical behavior and the keyword has no effect. |
There was a problem hiding this comment.
P1: This describes the configured value as a hard maximum, but the implementation defines eviction as best-effort. A connection becomes eligible for eviction after this duration and is discarded on a later retrieval or maintenance pass; the exact timing can vary by pool implementation and maintenance cadence. Please replace “configures the maximum time ... before the pool discards it” with wording such as “configures the idle duration after which a pooled connection becomes eligible for eviction.”
… Learn style alignment
|
All applied in 9c6c69e — thanks for the precise wordings, used them as given: idle-timeout eviction now described as best-effort eligibility (which also matches what we observed empirically: eviction lands on a later maintenance pass, timing varies with the sweep cadence), pool V2 marked experimental, and the style pass throughout the new sections (switch names as code, "at application startup", bolded data type names, the three-sentence latching note, and the user-facing failover wording). |
David Levy (dlevy-msft-sql)
left a comment
There was a problem hiding this comment.
The latest update addresses both technical findings and the Learn style suggestions. Thanks for the quick revisions.
|
Learn Build status updates of commit 9c6c69e: ✅ Validation status: passed
For more details, please refer to the build report. |
|
Learn Build status updates of commit e80893c: ❌ Validation status: errorsPlease follow instructions here which may help to resolve issue.
For more details, please refer to the build report. Note: Your PR may contain errors or warnings or suggestions unrelated to the files you changed. This happens when external dependencies like GitHub alias, Microsoft alias, cross repo links are updated. Please use these instructions to resolve them. |
|
Rebased onto current |
|
Learn Build status updates of commit 60a6c88: ✅ Validation status: passed
For more details, please refer to the build report. |
Addresses dotnet/SqlClient#3412 — the page had drifted from the code:
LocalAppContextSwitches.cson SqlClient's currentmaincarries five behavior switches this page doesn't mention. This PR adds one section per missing switch, in the page's existing format, with defaults and introduction versions verified against the source and release tags (6.0 / 6.1 / 7.1.0-preview2):Switch.Microsoft.Data.SqlClient.UseLegacyIdleTimeoutBehavior(7.1.0-preview2, defaulttrue) — gates whether theConnection Idle Timeoutconnection-string keyword is enforced at all.Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2(6.1, defaultfalse)Switch.Microsoft.Data.SqlClient.UseOverallConnectTimeoutForPoolWait(7.1.0-preview2, defaultfalse)Switch.Microsoft.Data.SqlClient.UseLegacyFailoverAlternationOnLoginSqlErrors(7.1.0-preview2, defaultfalse)Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviour(6.0, defaulttrue)It also adds a short cross-cutting note after the intro: switch values are read once and cached on first use, so a switch set after the first use of any SqlClient type is a silent no-op — none of the existing sections state this.
Two candidates were deliberately excluded:
UseMinimumLoginTimeout(a property name only — its switch string is the already-documentedUseOneSecFloorInTimeoutCalculationDuringLogin) andGlobalizationInvariantMode(reads the runtime'sSystem.Globalization.Invariant, not a SqlClient switch).