Skip to content

docs: correct TransparentNetworkIPResolution behavior wording (Fixes #4489) - #4493

Open
dlevy-msft-sql wants to merge 4 commits into
dotnet:mainfrom
dlevy-msft-sql:dev/automation/tnir-docs-4489
Open

docs: correct TransparentNetworkIPResolution behavior wording (Fixes #4489)#4493
dlevy-msft-sql wants to merge 4 commits into
dotnet:mainfrom
dlevy-msft-sql:dev/automation/tnir-docs-4489

Conversation

@dlevy-msft-sql

Copy link
Copy Markdown

Fixes #4489.

What changed

Three edits to the TransparentNetworkIPResolution documentation on both SqlConnection.ConnectionString and SqlConnectionStringBuilder.TransparentNetworkIPResolution:

  1. Replace the misleading 0.5 seconds phrasing with an accurate description of the multi-round retry loop, per the code in SqlConnectionInternal.LoginNoFailover and AdapterUtil.MinimumTimeoutForTnirMs.
  2. Expand the Authentication list from two methods to the full Entra ID set plus the access-token path, per SqlConnectionInternal.ShouldDisableTnir.
  3. Add the missing Azure SQL endpoint override and explicit-set escape hatch (netfx), and document the modern .NET (KeywordNotSupported) parse-throw behavior, per the #if NETFRAMEWORK guards in SqlConnectionOptions.cs and TdsParserStateObject.cs.

Wording follows the suggested text in #4489 and the follow-up correction comment on Bug 3.

Verification

  • Ran Select-String for the removed TNIR phrases; no matches remain in the TNIR documentation.
  • Both XML files parse as well-formed XML.
  • Snippet rendering is flagged for the docs build to verify.

Copilot AI review requested due to automatic review settings July 30, 2026 15:51
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Jul 30, 2026
@dlevy-msft-sql
dlevy-msft-sql force-pushed the dev/automation/tnir-docs-4489 branch from 88f180f to 6abfe58 Compare July 30, 2026 15:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the TransparentNetworkIPResolution documentation to match the current implementation behavior, primarily for .NET Framework (TNIR retry/timeout behavior and automatic disable conditions), and clarifies the unsupported-keyword behavior on modern .NET.

Changes:

  • Replaces the misleading “0.5 seconds then parallel” description with a multi-round retry/timeout description aligned to the implementation.
  • Expands the documented Entra ID authentication cases and the AccessToken-related behavior that affect TNIR defaults on .NET Framework.
  • Documents the .NET (non-Framework) behavior where TransparentNetworkIPResolution is not a recognized keyword and parsing throws ArgumentException (KeywordNotSupported).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml Updates the TransparentNetworkIPResolution property documentation and remarks to reflect current TNIR behavior and keyword support by platform.
doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml Updates the connection-string keyword table entry for TransparentNetworkIPResolution to reflect current TNIR behavior and keyword support by platform.
Comments suppressed due to low confidence (1)

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1423

  • The Azure-endpoint paragraph suggests you can "restore the automatic override" by setting TransparentNetworkIPResolution=False, but that doesn't restore the automatic conditional behavior; it forces TNIR off for all connections. Also, after updating the previous paragraph to describe the Entra/AccessToken default-disable semantics, this paragraph can focus on the Azure SQL endpoint case to avoid duplication.
        <para>
          On .NET Framework, if <c>TransparentNetworkIPResolution</c> isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (<c>.database.windows.net</c>, <c>.database.cloudapi.de</c>, <c>.database.usgovcloudapi.net</c>, <c>.database.chinacloudapi.cn</c>, or <c>.database.fabric.microsoft.com</c>) or when <c>Authentication</c> uses a Microsoft Entra ID method. An explicit <c>TransparentNetworkIPResolution=True</c> in the connection string overrides this automatic behavior; to restore the automatic override, remove the keyword from the connection string, or set it explicitly to <c>False</c>.
        </para>

Comment thread doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml Outdated
Copilot AI review requested due to automatic review settings July 30, 2026 15:57
@dlevy-msft-sql
dlevy-msft-sql force-pushed the dev/automation/tnir-docs-4489 branch from 6abfe58 to ec43fd6 Compare July 30, 2026 15:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1423

  • This paragraph says TNIR is ignored when Authentication uses Entra ID or when AccessToken is set, but on .NET Framework that automatic disable only happens when TransparentNetworkIPResolution is NOT explicitly present in the connection string (SqlConnectionInternal.ShouldDisableTnir checks Parsetable.ContainsKey(...) and returns false when explicitly specified). Also, "TNIR" is introduced without expansion and "set it explicitly to False" does not restore the automatic behavior (it disables TNIR unconditionally).
          On .NET Framework, if <c>TransparentNetworkIPResolution</c> isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (<c>.database.windows.net</c>, <c>.database.cloudapi.de</c>, <c>.database.usgovcloudapi.net</c>, <c>.database.chinacloudapi.cn</c>, or <c>.database.fabric.microsoft.com</c>), when the <c>Authentication</c> key is set to any Microsoft Entra ID method (Active Directory Password, Integrated, Interactive, Service Principal, Device Code Flow, Managed Identity, MSI, Default, or Workload Identity), or if <c>AccessToken</c> is set. For these automatic conditions, an explicit <c>TransparentNetworkIPResolution</c> value bypasses the automatic behavior: <c>True</c> enables TNIR, and <c>False</c> disables TNIR unconditionally. To restore the automatic behavior, remove the keyword from the connection string.
        </para>
        <para>
          On .NET (Core, .NET 5+), <c>TransparentNetworkIPResolution</c> isn't a recognized connection-string keyword. Setting it (with any value) throws <c>ArgumentException</c> (<c>KeywordNotSupported</c>) when the driver parses the connection string.
        </para>

doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml:1024

  • This row describes TNIR as "trying one address at a time" and says it is ignored for Entra ID auth / AccessToken, but the .NET Framework implementation uses a sequential first attempt followed by parallel attempts (TdsParser.Connect sets TransparentNetworkResolutionState.SequentialMode only for the first attempt, otherwise ParallelMode) and it only auto-disables TNIR for Azure endpoints / federated auth when the keyword is NOT explicitly present in the connection string (SqlConnectionInternal.ShouldDisableTnir checks Parsetable.ContainsKey(...)). The wording should be adjusted to match the actual behavior and avoid implying the keyword is always ignored.
|Transparent Network IP Resolution<br /><br /> -or-<br /><br />TransparentNetworkIPResolution|See description.|On .NET Framework, when the value of this key is set to `true` (the default), the driver runs multiple connect rounds across the DNS-resolved IP addresses, trying one address at a time with a 500 ms floor on the first attempt and progressively larger per-attempt timeouts, until a connection succeeds or the overall `Connect Timeout` is reached.<br /><br /> If the `MultiSubnetFailover` key is set to `true`, `TransparentNetworkIPResolution` is ignored.<br /><br /> If the `Failover Partner` key is set, `TransparentNetworkIPResolution` is ignored.<br /><br /> On .NET Framework, if `TransparentNetworkIPResolution` isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (`.database.windows.net`, `.database.cloudapi.de`, `.database.usgovcloudapi.net`, `.database.chinacloudapi.cn`, or `.database.fabric.microsoft.com`), when the `Authentication` key is set to any Microsoft Entra ID method (Active Directory Password, Integrated, Interactive, Service Principal, Device Code Flow, Managed Identity, MSI, Default, or Workload Identity), or if `AccessToken` is set. For these automatic conditions, an explicit `TransparentNetworkIPResolution` value bypasses the automatic behavior: `True` enables TNIR, and `False` disables TNIR unconditionally. To restore the automatic behavior, remove the keyword from the connection string.<br /><br /> On .NET (Core, .NET 5+), `TransparentNetworkIPResolution` isn't a recognized connection-string keyword. Setting it (with any value) throws `ArgumentException` (`KeywordNotSupported`) when the driver parses the connection string.<br /><br /> The value of this key must be `true`, `false`, `yes`, or `no`.<br /><br /> A value of `yes` is treated the same as a value of `true`.<br /><br /> A value of `no` is treated the same as a value of `false`.|

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1406

  • The summary says TNIR tries one address at a time for multiple rounds, but the implementation uses a sequential first attempt and then switches to parallel mode for subsequent attempts (TdsParser.Connect sets TransparentNetworkResolutionState.SequentialMode only for the first attempt, otherwise ParallelMode). The wording here should reflect the sequential-first / parallel-after behavior.
        On .NET Framework, when the value of this key is set to <see langword="true" /> (the default), the driver runs multiple connect rounds across the DNS-resolved IP addresses, trying one address at a time with a 500 ms floor on the first attempt and progressively larger per-attempt timeouts, until a connection succeeds or the overall <c>Connect Timeout</c> is reached.

Copilot AI review requested due to automatic review settings July 30, 2026 16:04
TransparentNetworkResolutionState alternates between SequentialMode and ParallelMode across attempts; the driver does not uniformly try one address at a time. Reverts that single sub-change and keeps the rest of the TNIR docs correction.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml:1024

  • This row says TNIR works by "trying one address at a time" with a 500 ms floor on the "first attempt". In netfx, TNIR has distinct sequential vs parallel modes (first attempt sequential, subsequent attempts parallel) as described by TransparentNetworkResolutionState (TdsEnums.cs) and selected in TdsParser.Connect. Consider updating this opening sentence so it doesn’t imply TNIR remains sequential for all rounds.
|Transparent Network IP Resolution<br /><br /> -or-<br /><br />TransparentNetworkIPResolution|See description.|On .NET Framework, when the value of this key is set to `true` (the default), the driver runs multiple connect rounds across the DNS-resolved IP addresses, with a 500 ms floor on the first attempt and progressively larger per-attempt timeouts, until a connection succeeds or the overall `Connect Timeout` is reached.<br /><br /> If the `MultiSubnetFailover` key is set to `true`, `TransparentNetworkIPResolution` is ignored.<br /><br /> If the `Failover Partner` key is set, `TransparentNetworkIPResolution` is ignored.<br /><br /> On .NET Framework, if `TransparentNetworkIPResolution` isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (`.database.windows.net`, `.database.cloudapi.de`, `.database.usgovcloudapi.net`, `.database.chinacloudapi.cn`, or `.database.fabric.microsoft.com`), when the `Authentication` key is set to any Microsoft Entra ID method (Active Directory Password, Integrated, Interactive, Service Principal, Device Code Flow, Managed Identity, MSI, Default, or Workload Identity), or if `AccessToken` is set. For these automatic conditions, an explicit `TransparentNetworkIPResolution` value bypasses the automatic behavior: `True` enables TNIR, and `False` disables TNIR unconditionally. To restore the automatic behavior, remove the keyword from the connection string.<br /><br /> On .NET (Core, .NET 5+), `TransparentNetworkIPResolution` isn't a recognized connection-string keyword. Setting it (with any value) throws `ArgumentException` (`KeywordNotSupported`) when the driver parses the connection string.<br /><br /> The value of this key must be `true`, `false`, `yes`, or `no`.<br /><br /> A value of `yes` is treated the same as a value of `true`.<br /><br /> A value of `no` is treated the same as a value of `false`.|

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1406

  • The summary describes TNIR as "trying one address at a time" with a 500 ms floor on the "first attempt", but the implementation uses distinct sequential vs parallel TNIR modes (first attempt sequential, subsequent attempts parallel) via TransparentNetworkResolutionState (TdsEnums.cs) and TdsParser.Connect. As written, the summary reads like TNIR stays sequential for all rounds and may mislead about later parallel attempts.
        On .NET Framework, when the value of this key is set to <see langword="true" /> (the default), the driver runs multiple connect rounds across the DNS-resolved IP addresses, with a 500 ms floor on the first attempt and progressively larger per-attempt timeouts, until a connection succeeds or the overall <c>Connect Timeout</c> is reached.

Copilot AI review requested due to automatic review settings July 30, 2026 16:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1406

  • This summary calls “the default”, but TNIR can be automatically disabled when the keyword is not present (Azure SQL endpoint / Entra ID / AccessToken), making the effective default conditional. Dropping “(the default)” avoids implying TNIR is always enabled by default.
        On .NET Framework, when the value of this key is set to <see langword="true" /> (the default), the driver runs multiple connect rounds across the DNS-resolved IP addresses, with a 500 ms floor on the first attempt and progressively larger per-attempt timeouts, until a connection succeeds or the overall <c>Connect Timeout</c> is reached.

doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml:1024

  • This row (1) describes true as “the default” even though TNIR is automatically disabled in some cases when the keyword is absent, (2) lists Entra ID Authentication values in an abbreviated form that doesn’t match the accepted connection-string values (e.g., “Active Directory Integrated”, “Active Directory MSI”), and (3) states “The value of this key must be …” without scoping it to .NET Framework even though the preceding sentence says the keyword is not recognized on modern .NET. Tweaking the wording to remove ambiguity keeps the table consistent and copy/paste-safe.
|Transparent Network IP Resolution<br /><br /> -or-<br /><br />TransparentNetworkIPResolution|See description.|On .NET Framework, when the value of this key is set to `true` (the default), the driver runs multiple connect rounds across the DNS-resolved IP addresses, with a 500 ms floor on the first attempt and progressively larger per-attempt timeouts, until a connection succeeds or the overall `Connect Timeout` is reached.<br /><br /> If the `MultiSubnetFailover` key is set to `true`, `TransparentNetworkIPResolution` is ignored.<br /><br /> If the `Failover Partner` key is set, `TransparentNetworkIPResolution` is ignored.<br /><br /> On .NET Framework, if `TransparentNetworkIPResolution` isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (`.database.windows.net`, `.database.cloudapi.de`, `.database.usgovcloudapi.net`, `.database.chinacloudapi.cn`, or `.database.fabric.microsoft.com`), when the `Authentication` key is set to any Microsoft Entra ID method (Active Directory Password, Integrated, Interactive, Service Principal, Device Code Flow, Managed Identity, MSI, Default, or Workload Identity), or if `AccessToken` is set. For these automatic conditions, an explicit `TransparentNetworkIPResolution` value bypasses the automatic behavior: `True` enables TNIR, and `False` disables TNIR unconditionally. To restore the automatic behavior, remove the keyword from the connection string.<br /><br /> On .NET (Core, .NET 5+), `TransparentNetworkIPResolution` isn't a recognized connection-string keyword. Setting it (with any value) throws `ArgumentException` (`KeywordNotSupported`) when the driver parses the connection string.<br /><br /> The value of this key must be `true`, `false`, `yes`, or `no`.<br /><br /> A value of `yes` is treated the same as a value of `true`.<br /><br /> A value of `no` is treated the same as a value of `false`.|

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1419

  • The list of Microsoft Entra ID authentication methods is written in abbreviated form (e.g., “Integrated”, “MSI”, “Default”), but the driver’s accepted Authentication connection-string values are the full strings (for example “Active Directory Integrated”, “Active Directory MSI”, “Active Directory Default”, etc.; see DbConnectionStringUtilities.cs). Using the exact values prevents users from copy/pasting a value that won’t parse.
          On .NET Framework, if <c>TransparentNetworkIPResolution</c> isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (<c>.database.windows.net</c>, <c>.database.cloudapi.de</c>, <c>.database.usgovcloudapi.net</c>, <c>.database.chinacloudapi.cn</c>, or <c>.database.fabric.microsoft.com</c>), when the <c>Authentication</c> key is set to any Microsoft Entra ID method (Active Directory Password, Integrated, Interactive, Service Principal, Device Code Flow, Managed Identity, MSI, Default, or Workload Identity), or if <c>AccessToken</c> is set. For these automatic conditions, an explicit <c>TransparentNetworkIPResolution</c> value bypasses the automatic behavior: <c>True</c> enables TNIR, and <c>False</c> disables TNIR unconditionally. To restore the automatic behavior, remove the keyword from the connection string.

- Drop '(the default)' from the summary sentence: TNIR is auto-disabled when the keyword is absent for Azure SQL/Entra/AccessToken, so calling 'true' the effective default is misleading.

- Expand the Entra ID Authentication list to the full connection-string values (Active Directory Password, Active Directory Integrated, ...), which are the strings the parser accepts (DbConnectionStringUtilities.cs).

- Scope 'The value of this key must be true/false/yes/no' to .NET Framework, matching the preceding paragraph that says the keyword is unrecognized on modern .NET.
Copilot AI review requested due to automatic review settings July 30, 2026 16:26
@dlevy-msft-sql

Copy link
Copy Markdown
Author

@dotnet-policy-service agree company="Microsoft"

@dlevy-msft-sql dlevy-msft-sql self-assigned this Jul 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1422

  • The docs mention "KeywordNotSupported" in parentheses, but that's an internal resource/helper identifier rather than a user-visible exception type. Public docs should generally state the exception type (ArgumentException) without exposing internal string/resource names.
          On .NET (Core, .NET 5+), <c>TransparentNetworkIPResolution</c> isn't a recognized connection-string keyword. Setting it (with any value) throws <c>ArgumentException</c> (<c>KeywordNotSupported</c>) when the driver parses the connection string.

doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml:1024

  • This row describes the 500 ms minimum as being on the "first attempt" and also references "KeywordNotSupported". In the current .NET Framework implementation the 500 ms floor is tied to the attempt treated as the sequential TNIR attempt, and "KeywordNotSupported" is an internal resource/helper name (not a public exception type). Consider rewording both phrases for accuracy and to avoid leaking internal identifiers.
|Transparent Network IP Resolution<br /><br /> -or-<br /><br />TransparentNetworkIPResolution|See description.|On .NET Framework, when the value of this key is set to `true`, the driver runs multiple connect rounds across the DNS-resolved IP addresses, with a 500 ms floor on the first attempt and progressively larger per-attempt timeouts, until a connection succeeds or the overall `Connect Timeout` is reached.<br /><br /> If the `MultiSubnetFailover` key is set to `true`, `TransparentNetworkIPResolution` is ignored.<br /><br /> If the `Failover Partner` key is set, `TransparentNetworkIPResolution` is ignored.<br /><br /> On .NET Framework, if `TransparentNetworkIPResolution` isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (`.database.windows.net`, `.database.cloudapi.de`, `.database.usgovcloudapi.net`, `.database.chinacloudapi.cn`, or `.database.fabric.microsoft.com`), when the `Authentication` key is set to any Microsoft Entra ID method (`Active Directory Password`, `Active Directory Integrated`, `Active Directory Interactive`, `Active Directory Service Principal`, `Active Directory Device Code Flow`, `Active Directory Managed Identity`, `Active Directory MSI`, `Active Directory Default`, or `Active Directory Workload Identity`), or if `AccessToken` is set. For these automatic conditions, an explicit `TransparentNetworkIPResolution` value bypasses the automatic behavior: `True` enables TNIR, and `False` disables TNIR unconditionally. To restore the automatic behavior, remove the keyword from the connection string.<br /><br /> On .NET (Core, .NET 5+), `TransparentNetworkIPResolution` isn't a recognized connection-string keyword. Setting it (with any value) throws `ArgumentException` (`KeywordNotSupported`) when the driver parses the connection string.<br /><br /> On .NET Framework, the value of this key must be `true`, `false`, `yes`, or `no`.<br /><br /> A value of `yes` is treated the same as a value of `true`.<br /><br /> A value of `no` is treated the same as a value of `false`.|

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1406

  • The summary says the 500 ms minimum applies on the "first attempt", but the current .NET Framework implementation applies the 500 ms floor only for the attempt flagged as the sequential TNIR attempt (see LoginNoFailover's isFirstTransparentAttempt + MinimumTimeoutForTnirMs). Rewording avoids documenting a specific attempt order that doesn't match the implementation.
        On .NET Framework, when the value of this key is set to <see langword="true" />, the driver runs multiple connect rounds across the DNS-resolved IP addresses, with a 500 ms floor on the first attempt and progressively larger per-attempt timeouts, until a connection succeeds or the overall <c>Connect Timeout</c> is reached.

- '500 ms floor on the first attempt' misrepresents the code: the floor is applied when SqlConnectionInternal sets isFirstTransparentAttempt (attemptNumber == 1), which corresponds to TransparentNetworkResolutionState.SequentialMode in TdsParser.Connect. Reword to 'a 500 ms minimum on the sequential-mode attempt'.

- Drop the '(KeywordNotSupported)' parenthetical from the modern-.NET paragraph: that's an SR resource key, not the public exception type.
Copilot AI review requested due to automatic review settings July 30, 2026 17:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml:1419

  • The remark mentions "AccessToken" as if it were a connection-string keyword, but SqlClient's TNIR auto-disable check is based on the connection's SqlConnection.AccessToken property (there is no AccessToken connection-string keyword). This wording can confuse readers of a connection-string keyword doc block.
          On .NET Framework, if <c>TransparentNetworkIPResolution</c> isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (<c>.database.windows.net</c>, <c>.database.cloudapi.de</c>, <c>.database.usgovcloudapi.net</c>, <c>.database.chinacloudapi.cn</c>, or <c>.database.fabric.microsoft.com</c>), when the <c>Authentication</c> key is set to any Microsoft Entra ID method (<c>Active Directory Password</c>, <c>Active Directory Integrated</c>, <c>Active Directory Interactive</c>, <c>Active Directory Service Principal</c>, <c>Active Directory Device Code Flow</c>, <c>Active Directory Managed Identity</c>, <c>Active Directory MSI</c>, <c>Active Directory Default</c>, or <c>Active Directory Workload Identity</c>), or if <c>AccessToken</c> is set. For these automatic conditions, an explicit <c>TransparentNetworkIPResolution</c> value bypasses the automatic behavior: <c>True</c> enables TNIR, and <c>False</c> disables TNIR unconditionally. To restore the automatic behavior, remove the keyword from the connection string.

doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml:1024

  • This connection-string keyword table row says "or if AccessToken is set", which reads like AccessToken is a connection-string keyword. In the implementation, the TNIR auto-disable condition is based on the SqlConnection.AccessToken property being set (there is no AccessToken connection-string keyword). Clarifying this avoids misleading readers.
|Transparent Network IP Resolution<br /><br /> -or-<br /><br />TransparentNetworkIPResolution|See description.|On .NET Framework, when the value of this key is set to `true`, the driver runs multiple connect rounds across the DNS-resolved IP addresses, with progressively larger per-attempt timeouts and a 500 ms minimum on the sequential-mode attempt, until a connection succeeds or the overall `Connect Timeout` is reached.<br /><br /> If the `MultiSubnetFailover` key is set to `true`, `TransparentNetworkIPResolution` is ignored.<br /><br /> If the `Failover Partner` key is set, `TransparentNetworkIPResolution` is ignored.<br /><br /> On .NET Framework, if `TransparentNetworkIPResolution` isn't specified in the connection string, the driver automatically disables TNIR when the data source is an Azure SQL endpoint (`.database.windows.net`, `.database.cloudapi.de`, `.database.usgovcloudapi.net`, `.database.chinacloudapi.cn`, or `.database.fabric.microsoft.com`), when the `Authentication` key is set to any Microsoft Entra ID method (`Active Directory Password`, `Active Directory Integrated`, `Active Directory Interactive`, `Active Directory Service Principal`, `Active Directory Device Code Flow`, `Active Directory Managed Identity`, `Active Directory MSI`, `Active Directory Default`, or `Active Directory Workload Identity`), or if `AccessToken` is set. For these automatic conditions, an explicit `TransparentNetworkIPResolution` value bypasses the automatic behavior: `True` enables TNIR, and `False` disables TNIR unconditionally. To restore the automatic behavior, remove the keyword from the connection string.<br /><br /> On .NET (Core, .NET 5+), `TransparentNetworkIPResolution` isn't a recognized connection-string keyword. Setting it (with any value) throws `ArgumentException` when the driver parses the connection string.<br /><br /> On .NET Framework, the value of this key must be `true`, `false`, `yes`, or `no`.<br /><br /> A value of `yes` is treated the same as a value of `true`.<br /><br /> A value of `no` is treated the same as a value of `false`.|

@cheenamalhotra cheenamalhotra added Hotfix 7.0.3 PRs targeting main that should be backported to release/7.0 branch for next release. Hotfix 6.1.7 PRs targeting main that should be backported to release/6.1 branch for future hotfix labels Jul 30, 2026
@cheenamalhotra cheenamalhotra added this to the 7.1.0-preview3 milestone Jul 30, 2026
@cheenamalhotra cheenamalhotra added the Area\Documentation Use this for issues that requires changes in public documentations/samples. label Jul 30, 2026
@dlevy-msft-sql
dlevy-msft-sql marked this pull request as ready for review July 30, 2026 18:25
@dlevy-msft-sql
dlevy-msft-sql requested a review from a team as a code owner July 30, 2026 18:25
@cheenamalhotra cheenamalhotra moved this from To triage to In review in SqlClient Board Jul 30, 2026

@paulmedynski paulmedynski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does the TNIR default behaviour described in these changes apply when using the SqlConnection properties AccessToken and AccessTokenCallback directly?

@dlevy-msft-sql

Copy link
Copy Markdown
Author

How does the TNIR default behaviour described in these changes apply when using the SqlConnection properties AccessToken and AccessTokenCallback directly?

I was unaware of that - thanks! Updated here and in the Learn docs PR: https://github.com/MicrosoftDocs/sql-docs-pr/pull/37729

@paulmedynski paulmedynski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's what actually happens if the SqlConnection API is used to set AccessToken or AccessTokenCallback:

Yes for SqlConnection.AccessToken; no for SqlConnection.AccessTokenCallback, based on the current .NET Framework implementation.

  • Setting SqlConnection.AccessToken through the API eventually populates _accessTokenInBytes. ShouldDisableTnir checks that field:

    bool isFedAuthEnabled = _accessTokenInBytes != null || ...

    Therefore, if TransparentNetworkIPResolution is absent from the connection string, an API-supplied AccessToken automatically disables TNIR on .NET Framework.

  • Setting only SqlConnection.AccessTokenCallback does not currently cause ShouldDisableTnir to return true. The callback is recognized later when constructing the federated-authentication request, but it is not included in the TNIR-disable predicate. Thus, unless another condition applies—such as an Azure SQL endpoint or an Entra authentication method in the connection string—TNIR is not automatically disabled solely because AccessTokenCallback was set.

The relevant logic is in SqlConnectionInternal.ShouldDisableTnir. The connection setup confirms that the callback is handled separately from the access-token field in SqlConnection.cs.

So the documentation change appears to need an additional clarification:

On .NET Framework, an API-supplied AccessToken disables TNIR automatically when the keyword is omitted. An API-supplied AccessTokenCallback does not, by itself, disable TNIR.

This applies only to .NET Framework, where TNIR is implemented. On modern .NET, TransparentNetworkIPResolution is an unsupported connection-string keyword.

I think we should call this out in the docs, and perhaps we have a real bug in the AccessTokenCallback case.

@github-project-automation github-project-automation Bot moved this from In review to Waiting for customer in SqlClient Board Aug 6, 2026
@cheenamalhotra

Copy link
Copy Markdown
Member

I think we should call this out in the docs, and perhaps we have a real bug in the AccessTokenCallback case.

Since this is a fairly new introduction, we should fix it in our driver to match what happens in the 'AccessToken' usecase. Documenting this would not be needed in that case.

@cheenamalhotra

Copy link
Copy Markdown
Member

@dlevy-msft-sql given that the fix will address the AccessTokenCallback issue, could you please adjust the doc updates? Also, the updates need not be backported, as the latest version API docs from 7.1 will be available to all versions.

@cheenamalhotra cheenamalhotra removed Hotfix 7.0.3 PRs targeting main that should be backported to release/7.0 branch for next release. Hotfix 6.1.7 PRs targeting main that should be backported to release/6.1 branch for future hotfix labels Aug 8, 2026
learn-build-service-prod Bot pushed a commit to MicrosoftDocs/sql-docs that referenced this pull request Aug 12, 2026
TransparentNetworkIPResolution defaults to true on .NET Framework and stays enabled against Azure SQL endpoints, which causes the driver to run its own per-attempt retry loop against a routed endpoint until the overall Connect Timeout is reached instead of returning to the Azure SQL gateway.

Adds a WARNING with the exact 'Connection Timeout Expired ... pre-login handshake acknowledgement' error text so affected users can find the workaround through search, plus the connection-string form of the fix (TransparentNetworkIPResolution=False) and references to dotnet/SqlClient#3528 and #3574.

Clarify AppContext switch instructions

Removed references to specific GitHub issues for clarity.

Correct TNIR warning: target explicit setting on Azure endpoints

The prior warning claimed TransparentNetworkIPResolution 'stays enabled even against Azure endpoints' on .NET Framework, which is only true when the connection string sets TNIR explicitly. Microsoft.Data.SqlClient's ShouldDisableTnir (netfx-only, present since 1.0 GA and inherited from the .NET Framework System.Data.SqlClient reference source) checks connectionOptions.Parsetable.ContainsKey for TransparentNetworkIpResolution. If the key isn't in the connection string, the driver disables TNIR automatically for Azure endpoints and for Microsoft Entra ID auth methods. If the key IS in the connection string, the explicit value wins and the Azure override is bypassed.

Rewrite the warning to target the actual failure mode (explicit TransparentNetworkIPResolution=True in a .NET Framework connection string against Azure SQL) and correct the follow-up guidance: the DisableTNIRByDefaultInConnectionString AppContext switch only flips the default value used when the key is absent, so it does not fix the explicit-set case. Recommend removing the key from the connection string as the primary fix.

Also clarify that TransparentNetworkIPResolution is ignored on modern .NET; only MultiSubnetFailover participates in parallel-connect on netcore.

Verified against SqlConnectionInternal.ShouldDisableTnir and DbConnectionStringDefaults.TransparentNetworkIpResolution in dotnet/SqlClient main.

docs: scope TNIR warning to .NET Framework and call out modern .NET parse error

Apply suggestions from code review

Co-authored-by: learn-build-service-prod-04[bot] <274428985+learn-build-service-prod-04[bot]@users.noreply.github.com>

docs: replace TNIR behavior-code lookup with a self-contained table

docs: align TNIR wording with dotnet/SqlClient PR #4493

Match the canonical XML doc snippet updates in dotnet/SqlClient#4493:
- add `the overall` qualifier before `Connect Timeout` in the behavior table
- add `(with any value)` to the modern .NET parse-throw sentence
- enumerate the five Azure SQL endpoint suffixes
- enumerate all nine Microsoft Entra ID authentication methods
- add the `AccessToken` auto-disable condition
- tighten the explicit-set language: `True` enables, `False` disables unconditionally

docs: recommend MultiSubnetFailover for parallel connections

docs: restore unrelated rowversion wording

docs: reframe MultiSubnetFailover guidance around multiple target IPs

Per CSS feedback (Chris Roeszler, Chrone Meade): MultiSubnetFailover
isn't about multiple subnets, it's about multiple target IPs. A listener
with 2+ IPs in the same subnet benefits from MSF too. Reframe the
warning paragraph to lead with "multiple target IPs" and add a
"despite the name" clarification so readers don't wonder whether their
same-subnet scenario qualifies.

docs: broaden TNIR warning to cover on-prem AG listeners and multi-IP DNS

The previous warning framed TNIR delays as an Azure SQL problem. The
underlying mechanism, sequential per-IP walk with growing per-attempt
timeouts, hits any topology whose DNS name resolves to multiple IPs.
On-premises AG listeners and multi-subnet cluster listeners see the
same pre-login handshake timeout as Azure SQL.

Lead with the generic mechanism, then list the affected topologies
(Azure SQL, AG listener, FCI/DNS round-robin) and split the mitigation
guidance so on-prem readers know the automatic override doesn't help
and they need explicit False or the AppContext switch.

docs: drop Connect Retry Count=0 clause from TNIR warning

Per PR #37729 review feedback: the claim reads like a bug on first
encounter, and a dedicated tracking issue on dotnet/SqlClient is the
right place to resolve whether it's intentional. Drop the sentence
from the WARNING; readers who want to know why CRC=0 doesn't stop the
TNIR loop can find the answer in the SqlClient issue tracker.

docs: recommend always setting TransparentNetworkIPResolution=False

Elevate the recommendation to unconditional on .NET Framework: set
TransparentNetworkIPResolution=False on every connection string,
regardless of whether the target is Azure SQL or on-premises SQL
Server. Add a TIP callout above the behavior discussion and rewrite
the WARNING mitigation section to lead with the unconditional guidance
instead of branching by target. Keep the automatic-override background,
process-wide AppContext switch option, and MultiSubnetFailover advice
as follow-ons.

docs: replace "modern .NET" jargon with explicit version enumeration

"Modern .NET" is Microsoft docs-team shorthand that assumes the reader
already knows the .NET Framework vs .NET Core vs .NET 5+ history. Spell
out the concrete versions on every mention:

- Table intro paragraph: ".NET Core and .NET 5 or later versions of .NET"
  and follow-up "On those versions".
- Add a NOTE callout that pins down the terminology: .NET Framework
  4.6.2-4.8.1 vs the cross-platform runtime that started as .NET Core
  and was renamed to ".NET" starting with .NET 5.
- WARNING trailer: ".NET Core, .NET 5, or later versions".

docs: recommend MultiSubnetFailover=True as the universal fix for TNIR

Replace the "set TransparentNetworkIPResolution=False" recommendation
with "set MultiSubnetFailover=True". MSF=True short-circuits TNIR at
the driver level (isParallel = MSF || (TNIR && !disableTnir)), so the
parallel-connect path fixes the sequential per-IP retry loop without
touching the TNIR keyword. Advantages:

- Works uniformly on .NET Framework, .NET Core, .NET 5, and later
  (whereas TNIR=False is .NET Framework only).
- Aligns with the EnableMultiSubnetFailoverByDefault AppContext switch
  documented at the top of this same article.
- Safe on stand-alone servers whose DNS resolves to a single IP.

Also delete the "modern .NET" terminology NOTE callout (redundant now
that the version enumeration is inline) and drop the trailing "don't
set TNIR=False on .NET Core" warning (no longer needed once we don't
recommend setting TNIR at all).

docs: add troubleshooting entry for slow pre-login handshake with multi-IP DNS

Apply suggestions from code review

Co-authored-by: learn-build-service-prod-05[bot] <274429479+learn-build-service-prod-05[bot]@users.noreply.github.com>
Co-authored-by: learn-build-service-prod-03[bot] <274428581+learn-build-service-prod-03[bot]@users.noreply.github.com>

Fix typo in SQL client troubleshooting guide

Corrected a typographical error in the troubleshooting guide.

Apply suggestions from code review

Co-authored-by: learn-build-service-prod-05[bot] <274429479+learn-build-service-prod-05[bot]@users.noreply.github.com>

docs: broaden MSF=True guidance to any target and cross-link TNIR troubleshooting

docs: drop SQL Server 2012 references from HA/DR article

docs: replace retired SQL Server Books Online link with Learn page

Apply suggestions from code review

Co-authored-by: learn-build-service-prod-07[bot] <274430390+learn-build-service-prod-07[bot]@users.noreply.github.com>
Co-authored-by: learn-build-service-prod-08[bot] <274430765+learn-build-service-prod-08[bot]@users.noreply.github.com>

docs: clarify TNIR auto-disable for AccessToken vs AccessTokenCallback

docs: scope MultiSubnetFailover to TCP endpoints and note SqlClient constraints

SqlClient rejects MultiSubnetFailover on named instances (SNI error 48, TdsParser.cs:1752-1755) and on non-TCP protocols (error 49), so 'any SQL Server target' would send readers into an exception. Also uses 'authentication' rather than 'login' to match the sibling driver articles.

Apply suggestions from code review

Co-authored-by: Randolph West MSFT <97149825+rwestMSFT@users.noreply.github.com>
Co-authored-by: learn-build-service-prod-07[bot] <274430390+learn-build-service-prod-07[bot]@users.noreply.github.com>

docs: address review feedback on TNIR guidance

Replace 'floor' with a plain minimum, replace 'walks' with 'tries', and convert the oversized warning box into regular subsections so the AppContext switch content keeps its own heading.

docs: link to the driver reference instead of listing Azure SQL endpoint suffixes

The suffixes are hardcoded in Microsoft.Data.SqlClient (AdapterUtil.cs s_azureSqlServerEndpoints) and are already published in the TransparentNetworkIPResolution entry of the SqlConnection.ConnectionString reference, which is generated from the driver repo and tracks the driver. No other sql-docs article duplicates the list.

docs: drop the AccessTokenCallback TNIR carve-out

Per cheenamalhotra on dotnet/SqlClient#4493, the AccessTokenCallback behavior is being fixed in the driver to match AccessToken, so documenting the difference isn't needed. The mention was already removed from the driver's own reference in that PR; this keeps the Learn article consistent. Also adopts the PR's 'remove the keyword to restore automatic behavior' phrasing.

Apply suggestions from code review

Co-authored-by: learn-build-service-prod-01[bot] <274427437+learn-build-service-prod-01[bot]@users.noreply.github.com>

docs: use 'increases' consistently for the TNIR per-attempt timeout

Apply suggestions from code review

Co-authored-by: Randolph West MSFT <97149825+rwestMSFT@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area\Documentation Use this for issues that requires changes in public documentations/samples.

Projects

Status: Waiting for customer

Development

Successfully merging this pull request may close these issues.

Docs: SqlConnection.ConnectionString TransparentNetworkIPResolution row misrepresents actual behavior

4 participants