SqlClient の AppContext 切り替え

適用対象: .NET Framework .NET .NET Standard

ADO.NET のダウンロード

AppContext クラスを使用すれば、SqlClient によって、以前の動作に依存する呼び出し元を引き続きサポートしながら、新しい機能を提供することができます。 ユーザーは、特定の AppContext スイッチを設定することによって、動作の変更をオプトアウトすることができます。

SqlClientは各スイッチを初めて使用した際に読み取りとキャッシュを行います。 アプリケーション起動時にスイッチを設定し、SqlClientタイプを使う前に設定してください。 SqlClientが値をキャッシュした後にスイッチを変更しても影響はありません。

MultiSubnetFailover を既定で有効にする

適用対象: .NET Framework、.NET、.NET Standard

(バージョン 7.0 以降で使用可能)

個々の接続文字列を変更せずにグローバルに MultiSubnetFailover=true を設定するには、アプリケーション起動時にAppContextスイッチ Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefaulttrue に設定してください:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault", true);

App.Config でこのスイッチを有効にすることもできます。

<runtime>
  <AppContextSwitchOverrides value="Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault=true" />
</runtime>

有効にすると、すべての接続は接続文字列に MultiSubnetFailover=true が設定されているかのように動作します。 このスイッチは既定で無効になっています。

非同期読み取りのパケット多重化を有効にする

適用対象: .NET Framework、.NET、.NET Standard

(バージョン 7.0 以降で使用可能)

パケット多重化により、大きな結果セットを使用した ExecuteReaderAsync 、ストリーミング シナリオ、一括データ取得などの大規模な非同期読み取り操作のパフォーマンスが向上します。 この機能は、2 つのオプトイン AppContext スイッチによって制御されます。 両方のスイッチを false に設定すると、新しい非同期処理パスが有効になります。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseCompatibilityAsyncBehaviour", false);
AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseCompatibilityProcessSni", false);

既定では、両方のスイッチが trueされ、既存の (互換性のある) 動作が保持されます。

ユーザー エージェント機能拡張機能を有効にする

適用対象: .NET Framework、.NET、.NET Standard

(バージョン 7.0 以降で使用可能)

AppContextスイッチ Switch.Microsoft.Data.SqlClient.EnableUserAgent を有効にすると、ドライバーは接続の一部としてユーザーエージェントの詳細をサーバーに送信します。 この情報は、バージョンとオペレーティング システムによるドライバーの使用状況のトラブルシューティングと定量化に役立つ情報です。 このスイッチは既定で無効になっています。 これを有効にするには、アプリケーションの起動時に AppContext スイッチを true に設定します。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.EnableUserAgent", true);

10 進数の切り捨て動作を有効にする

適用対象: .NET Framework、.NET、.NET Standard

Microsoft.Data.SqlClient 2.0 以降、SQL Server と同様に、10 進データはデフォルトで四捨五入されます。 以前の切断動作を有効にするには、アプリケーション起動時にAppContextスイッチ Switch.Microsoft.Data.SqlClient.TruncateScaledDecimaltrue に設定できます:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal", true);

Windows でマネージド ネットワークを有効にする

適用対象: .NET、.NET Standard

(バージョン 2.0 以降で使用できます)

Windows 上の SqlClient では既定では SNI ネットワーク インターフェイスのネイティブ実装が使用されます。 マネージドSNI実装の使用を有効にするには、アプリケーション起動時にAppContextスイッチSwitch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindowstrueに設定します:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows", true);

このスイッチは、Windows 上の .NET Core 2.1 以降および .NET Standard 2.0 以降のプロジェクトでマネージド ネットワーク実装を使用するようにドライバーの動作を切り替え、Microsoft.Data.SqlClient ライブラリのネイティブ ライブラリへの依存関係をすべて排除します。 これはテストとデバッグのみを目的としています。

注意

ネイティブ実装と比較すると、いくつかの既知の相違点があります。 例えば、管理された実装は非ドメインのWindows認証をサポートしていません。

透過的なネットワーク IP の解決を無効にする

適用対象: .NET Framework

透過的なネットワーク IP の解決 (TNIR) は、既存の MultiSubnetFailover 機能の改訂です。 TNIR は、ホスト名の解決された最初の IP が応答せず、ホスト名に複数の IP が関連付けられている場合に、ドライバーの接続シーケンスに影響を及ぼします。 TransparentNetworkIPResolutionMultiSubnetFailoverの組み合わせは接続シーケンスを選択します:

TransparentNetworkIPResolution MultiSubnetFailover 接続シーケンス
True True TransparentNetworkIPResolution は無視されます。 ドライバーはDNSで解決されたIPアドレスを並列に試み、最初の応答者との認証を完成させます。
True ドライバーはDNSで解決されたIPアドレスに対して複数回の接続ラウンドを実行し、初回の試みは最低500ミリ秒、そして接続成功または全体の Connect Timeout に達するまで、1回目のタイムアウトは徐々に大きくなります。
True ドライバーはDNSで解決されたIPアドレスを並列に試み、最初の応答者との認証を完成させます。
ドライバーは、DNS で解決された各 IP アドレスへの接続を順に試み、いずれかが成功するか、Connect Timeout に達するまで続行します。

TransparentNetworkIPResolution.NET Frameworkではデフォルトで有効であり、MultiSubnetFailoverはデフォルトで無効化されています。 .NET 5以降のバージョンでは、TransparentNetworkIPResolutionは認識された接続文字列キーワードではなく、任意の値で設定するとArgumentException(KeywordNotSupported)が投げられます。 これらのバージョンは MultiSubnetFailover のみをサポートします。 このセクションの残りの部分(自動オーバーライド、以下の警告の故障モード、およびAppContextスイッチ)は.NETフレームワークに適用されます。

ヒント

.NET のバージョンや、対象が Azure SQL かオンプレミスの SQL Server かどうかに関係なく、すべての接続文字列でMultiSubnetFailover=Trueを設定してください。 MultiSubnetFailover=True 最初のレスポンシブレプリカを素早く見つける並列接続コードパスを選択します。 .NETフレームワークでは、TNIRの逐次的なIPごとの再試行ループも回避します。これは長い接続遅延や認証前のハンドシェイクタイムアウトの一般的な原因です。

.NET Frameworkでは、接続文字列でTransparentNetworkIPResolutionが指定されていない場合、データソースが認識されたAzure SQLエンドポイントである場合、Authenticationキーが任意のMicrosoft Entra IDメソッド(Active Directory PasswordActive Directory IntegratedActive Directory InteractiveActive Directory Service PrincipalActive Directory Device Code FlowActive Directory Managed IdentityActive Directory MSIActive Directory Default、またはActive Directory Workload Identity)に設定されている場合、またはSqlConnection.AccessTokenプロパティが設定されている場合、ドライバーは自動的にTNIRを無効化します。 ドライバーが認識するエンドポイント接尾辞については、SqlConnection.ConnectionStringTransparentNetworkIPResolution エントリを参照してください。

明示的な TransparentNetworkIPResolution 値はこの自動動作を回避します。 True TNIRを有効にし、 False 無条件にTNIRを無効化します。 自動動作を復元するには、そのキーワードを接続文字列から削除してください。 また、接続文字列がカスタムCNAMEやvanity DNS名を通じてAzure SQLを指し示し、その接尾辞がAzure SQLエンドポイントとして認識されていない場合も自動オーバーライドは適用されません。 自動オーバーライドは特にAzure SQLを対象としており、オンプレミスのSQL Serverでは起動しないため、TNIRはデフォルトでオンになっています。

.NETフレームワーク上の長い接続遅延

.NET Frameworkでは、TransparentNetworkIPResolution=True(デフォルト)は、ターゲットDNS名が複数のIPに解決され、初期のIPの一つが不健康、古く、または到達不能になると、長い接続遅延や認証前のハンドシェイクタイムアウトを引き起こすことがあります。 TNIRは解決されたIPを順次に試行し、各ラウンドごとにタイムアウトを増やし、全体の Connect Timeout に達するまで続けます。 通常、予想外に長い接続遅延が起こり、その結果は以下のエラーで終わります:

Connection Timeout Expired.  The timeout period elapsed while attempting to consume the pre-authentication handshake acknowledgement.  This could be because the pre-authentication handshake failed or the server was unable to respond back in time.

このパターンはいくつかのトポロジーで現れます:

  • Azure SQL Database、Azure SQL Managed Instance、またはMicrosoft FabricのSQL Database。 Azure SQLゲートウェイは各認証をバックエンドレプリカにルーティングします。 ルーティング接続が失敗すると、TNIRはゲートウェイに戻らずにルーティングされたバックエンドを再試行するため、バックエンドフェイルオーバー中の遅延が延長されます。
  • DNS 名が複数のレプリカ IP に解決される Always On 可用性グループ リスナーの背後にあるオンプレミス SQL Server。 古いDNSエントリや不健康なレプリカIPは、TNIRが動作するレプリカに到達する前に順次試行されます。
  • マルチサブネットクラスタリスナーを持つフェイルオーバークラスタインスタンスや、ターゲットDNS名に複数の A/AAAA レコードを持つその他の構成(DNSラウンドロビンなど)などです。

この挙動を避けるために、接続文字列にMultiSubnetFailover=Trueを設定します:

MultiSubnetFailover=True

この推奨はすべての.NETバージョンで機能し、Azure SQLとオンプレミスのSQL Serverの両方をカバーしています。 MultiSubnetFailover=True時、ドライバはTransparentNetworkIPResolutionを無視し、DNSで解決されたIPアドレスを並列に試み、最初のレスポンシブレプリカとの認証を完成させます。 名前に反して、 MultiSubnetFailover は複数のターゲットIPにDNS名で解決されるリスナーに適用されます。IPが異なるサブネットに属していなくても、DNSが単一のIPに解決されるスタンドアロンサーバーでは安全です。

すべての接続文字列を編集せずにプロセス全体で制御する場合は、デフォルトのAppContextスイッチでEnable MultiSubnetFailoverをご利用ください。

AppContextスイッチでTNIRを無効にする

.NET Framework上でTransparentNetworkIPResolutionのデフォルト値をtrueからfalseに反転させるには、アプリケーション起動時にAppContextのスイッチSwitch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionStringtrueに設定してください。 このスイッチは接続文字列にTransparentNetworkIPResolutionがない時のみデフォルト値を変更し、明示的な値を上書きしません。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString", true);

これらのプロパティの設定方法の詳細については、「SqlConnection.ConnectionString プロパティ」を参照してください。

ログイン中に最小タイムアウトを有効にする

適用対象: .NET Framework、.NET、.NET Standard

ログイン試行が無期限に待たないようにするには、アプリ起動時にAppContextのスイッチSwitch.Microsoft.Data.SqlClient.UseOneSecFloorInTimeoutCalculationDuringLogintrueに設定できます:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseOneSecFloorInTimeoutCalculationDuringLogin", false);

ReadAsync のブロック動作を無効にする

適用対象: .NET Framework、.NET、.NET Standard

バージョン3.0からは非同期 ReadAsync 動作します。 以前のバージョンでは、ReadAsync を同期的に実行し、.NET Framework 上では呼び出しスレッドをブロックします。 このブロッキング動作を制御するには、アプリ起動時にAppContextスイッチ Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlockingtrue または false に設定してください:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking", false);

rowversionのnull動作を有効にする

適用対象: .NET Framework、.NET、.NET Standard

バージョン3.0以降、rowversionにnull値がある場合、SqlDataReaderは空のbyte[]ではなくDBNull値を返します。 空 byte[]を返すというレガシー動作を有効にするには、アプリケーション起動時にAppContextスイッチ Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior を有効にしてください。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior", true);

安全でない TLS 警告の抑制

適用対象: .NET Framework、.NET、.NET Standard

(バージョン 4.0.1 以降で使用できます)

接続文字列でEncrypt=falseを使うと、TLSバージョンが1.2以下の場合、コンソールはセキュリティ警告を表示します。 この警告を抑制するには、アプリケーション起動時に以下のAppContextスイッチを有効にしてください:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.SuppressInsecureTLSWarning", true);

サーバーが提供するフェールオーバーパートナーを無視する

適用対象: .NET Framework、.NET、.NET Standard

(バージョン 5.1.8、6.0.4、6.1.3 以降で使用可能)

フェールオーバー時に、サーバーから提供されるフェールオーバー パートナー情報は、接続文字列で提供されるフェールオーバー パートナー情報よりも優先されます。 サーバーによって提供されるフェールオーバー パートナー情報を無視し、接続文字列で提供されるフェールオーバー パートナー情報のみを考慮するには、アプリケーションの起動時に次の AppContext スイッチを有効にします。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.IgnoreServerProvidedFailoverPartner", true);

接続のアイドル タイムアウトを適用する

適用対象: .NET Framework、.NET、.NET Standard

バージョン7.1.0-preview2からは、Connection Idle Timeout 接続文字列キーワードがアイドル時間(秒単位)を設定し、その後プール接続が追放対象となります(デフォルト300;値が0になるとアイドル有効期限が無効になります)。 対象となる接続は後の回収やメンテナンスパスで破棄されるため、正確なタイミングはプールの実装やメンテナンスの頻度によって異なる場合があります。 このキーワードは、レガシーのアイドルタイムアウト動作が無効化された場合にのみ適用されます。 スイッチをデフォルトの値 trueにすると、プールは過去の動作を保持し、キーワードには影響がありません。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseLegacyIdleTimeoutBehavior", false);

V2接続プールを有効にしてください

適用対象: .NET Framework、.NET、.NET Standard

バージョン6.1以降、SqlClientには代替の実験的な接続プール実装(V2)が含まれています。 V1プールはデフォルトのままです(スイッチはデフォルトで false)。 V2プールへのオプトインするには、アプリケーション起動時にAppContextスイッチを有効にしてください Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2", true);

カウントプールは接続タイムアウトを待機します

適用対象: .NET Framework、.NET、.NET Standard

バージョン7.1.0-preview2からは、プールからの接続待ち時間が発信者の Connect Timeout 予算にカウントされるため、プールの待機とネットワーク接続の試みが合計タイムアウトを1回分担します。 スイッチがデフォルトの falseに設定されると、プール操作は完全な Connect Timeout を受け取り、ネットワーク接続の試みにはさらに全予算が割り当てられます。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseOverallConnectTimeoutForPoolWait", true);

ログインエラー時のレガシーフェイルオーバーの交互に戻す

適用対象: .NET Framework、.NET、.NET Standard

バージョン7.1.0-preview2以降、フェイルオーバー設定時に接続すると、ログインフェーズ中に返されたSQLエラーに対してSqlClientはフェイルオーバーパートナーと交互に動作しなくなりました。 レガシーの交互動作に戻すには、アプリケーション起動時にAppContextスイッチ Switch.Microsoft.Data.SqlClient.UseLegacyFailoverAlternationOnLoginSqlErrors を有効にしてください。 スイッチはデフォルトで falseになります。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseLegacyFailoverAlternationOnLoginSqlErrors", true);

vartimeパラメータに対して明確なゼロスケールを尊重してください

適用対象: .NET Framework、.NET、.NET Standard

デフォルトでは、 datetime2datetimeoffsetまたはtime パラメータのスケールを明示的に0に設定すると、SqlClientはスケール7を送信します。 バージョン6.0以降では、アプリケーション起動時に Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviourfalse に設定し、明示的なスケール0を保ちます。 スイッチはデフォルトで trueになります。

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviour", false);