AppContext-Schalter in SqlClient

Gilt für: .NET Framework .NET .NET Standard

Herunterladen von ADO.NET

Die AppContext-Klasse ermöglicht SqlClient das Bereitstellen neuer Funktionen, während weiterhin Aufrufer unterstützt werden, die vom vorherigen Verhalten abhängen. Benutzer können sich gegen Änderungen am Verhalten entscheiden, indem Sie bestimmte AppContext-Optionen festlegen.

SqlClient liest und cachet jeden Switch beim ersten Mal, wenn er diesen Switch verwendet. Stelle Switches beim Anwendungsstart ein, bevor du irgendwelche SqlClient-Typen verwendest. Das Ändern eines Switches, nachdem SqlClient seinen Wert zwischengespeichert hat, hat keine Auswirkung.

Standardmäßiges Aktivieren von MultiSubnetFailover

Gilt für: .NET Framework; .NET; .NET Standard

(Ab Version 7.0 verfügbar)

Um MultiSubnetFailover=true global festzulegen, ohne einzelne Verbindungszeichenfolgen zu ändern, legen Sie den AppContext-Switch Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault beim Anwendungsstart auf true fest:

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

Sie können diesen Schalter auch in Ihrer App.Config aktivieren:

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

Wenn diese Option aktiviert ist, verhalten sich alle Verbindungen so, als ob MultiSubnetFailover=true in der Verbindungszeichenfolge gesetzt ist. Dieser Schalter ist standardmäßig deaktiviert.

Aktivieren von Paket-Multiplexing für asynchrone Lesevorgänge

Gilt für: .NET Framework; .NET; .NET Standard

(Ab Version 7.0 verfügbar)

Paket-Multiplexing verbessert die Leistung für große asynchrone Lesevorgänge, wie ExecuteReaderAsync, bei umfangreichen Resultsets, Streamingszenarien oder Massen-Datenabrufen. Dieses Feature wird von zwei Opt-In-AppContext-Schaltern gesteuert. Beide Schalter auf false setzen aktiviert den neuen asynchronen Verarbeitungspfad:

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

Standardmäßig sind beide Schalter true, wodurch das vorhandene (kompatible) Verhalten beibehalten wird.

Aktivieren des Dezimalabkürzungsverhaltens

Gilt für: .NET Framework; .NET; .NET Standard

Ab Microsoft.Data.SqlClient 2.0 werden Dezimaldaten wie bei SQL Server standardmäßig gerundet. Um das vorherige Verhalten des Abschneidens zu aktivieren, können Sie beim Anwendungsstart den AppContext-Schalter Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal auf true setzen:

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

Aktivieren von verwalteten Netzwerken unter Windows

Gilt für: .NET; .NET Standard

(Verfügbar ab Version 2.0)

Unter Windows verwendet SqlClient standardmäßig eine native Implementierung der SNI-Netzwerkschnittstelle. Um die Nutzung einer verwalteten SNI-Implementierung zu ermöglichen, setzen Sie den AppContext-Schalter Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows auf true beim Anwendungsstart:

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

Diese Option schaltet das Verhalten des Treibers so um, dass in Projekten in .NET Core 2.1 und höher und in .NET Standard 2.0 und höher unter Windows eine verwaltete Netzwerkimplementierung verwendet wird. Dies beseitigt alle Abhängigkeiten von nativen Bibliotheken für die Microsoft.Data.SqlClient-Bibliothek. Die Option ist nur für Test- und Debugzwecke vorgesehen.

Hinweis

Im Vergleich zur nativen Implementierung gibt es einige bekannte Unterschiede. Zum Beispiel unterstützt die verwaltete Implementierung keine Windows-Authentifizierung außerhalb der Domäne.

Transparente IP-Auflösung im Netzwerk deaktivieren

Gilt für: .NET Framework

Die transparente Netzwerk-IP-Adressauflösung (Transparent Network IP Resolution, TNIR) ist eine Überarbeitung des vorhandenen MultiSubnetFailover-Features. TNIR wirkt sich auf die Verbindungssequenz des Treibers aus, wenn die erste aufgelöste IP-Adresse des Hostnamens nicht reagiert und dem Hostnamen mehrere IP-Adressen zugeordnet sind. Die Kombination von TransparentNetworkIPResolution und MultiSubnetFailover wählt die Verbindungssequenz:

Transparente Netzwerk-IP-Auflösung MultiSubnetFailover Verbindungssequenz
Wahr Wahr TransparentNetworkIPResolution wird ignoriert. Der Treiber versucht parallel die DNS-aufgelösten IP-Adressen und schließt die Authentifizierung mit dem ersten Antwortenden ab.
Wahr False Der Treiber führt mehrere Verbindungsrunden über die DNS-aufgelösten IP-Adressen durch, mit einem Minimum von 500 Millisekunden beim ersten Versuch und zunehmend größeren Timeouts pro Versuch, bis eine Verbindung erfolgreich ist oder das Gesamtergebnis Connect Timeout erreicht ist.
False Wahr Der Treiber versucht parallel die DNS-aufgelösten IP-Adressen und schließt die Authentifizierung mit dem ersten Antwortenden ab.
False False Der Treiber versucht jede DNS-aufgelöste IP-Adresse nacheinander, bis eine erfolgreich ist oder Connect Timeout erreicht wird.

TransparentNetworkIPResolutionist standardmäßig auf .NET Framework aktiviert und MultiSubnetFailover standardmäßig deaktiviert. Auf .NET 5 und neueren Versionen TransparentNetworkIPResolution ist kein anerkanntes Verbindungsstring-Schlüsselwort und das Setzen dieser (mit beliebigem Wert) wirft ArgumentException (KeywordNotSupported). Diese Versionen berücksichtigen nur MultiSubnetFailover. Der Rest dieses Abschnitts (die automatische Überschreibung, die Fehlermodi in der folgenden Warnung und der AppContext-Wechsel) gilt für das .NET Framework.

Tipp

Legen Sie MultiSubnetFailover=True in jeder Verbindungszeichenfolge fest, unabhängig von der .NET-Version oder davon, ob das Ziel Azure SQL oder ein lokaler SQL Server ist. MultiSubnetFailover=True wählt einen Parallel-Connect-Codepfad, der schnell die erste reaktionsfähige Replik findet. Unter .NET Framework umgeht es zudem die sequentielle Wiederholungsschleife pro IP-Adresse von TNIR, die eine häufige Ursache für lange Verbindungsverzögerungen und Handshake-Zeitüberschreitungen vor der Authentifizierung ist.

Wenn unter .NET Framework TransparentNetworkIPResolution nicht in der Verbindungszeichenfolge angegeben ist, deaktiviert der Treiber TNIR automatisch, wenn die Datenquelle ein erkannter Azure SQL-Endpunkt ist, wenn der Schlüssel Authentication auf eine beliebige Microsoft Entra ID-Methode festgelegt ist (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 oder Active Directory Workload Identity), oder wenn die Eigenschaft SqlConnection.AccessToken festgelegt ist. Für die Endpunkt-Suffixe, die der Treiber erkennt, siehe den TransparentNetworkIPResolution Eintrag in SqlConnection.ConnectionString.

Ein expliziter TransparentNetworkIPResolution Wert umgeht dieses automatische Verhalten: True aktiviert TNIR und False deaktiviert TNIR bedingungslos. Um das automatische Verhalten wiederherzustellen, entferne das Schlüsselwort aus der Verbindungszeichenfolge. Die automatische Überschreibung gilt auch nicht, wenn die Verbindungszeichenfolge über einen benutzerdefinierten CNAME- oder Vanity-DNS-Namen auf Azure SQL zeigt, dessen Suffix nicht als Azure SQL-Endpunkt erkannt wird. Die automatische Überschreibung zielt speziell auf Azure SQL ab; sie wird nicht für lokalen SQL Server ausgelöst, daher ist TNIR dort standardmäßig aktiviert.

Lange Verbindungsverzögerungen im .NET Framework

Unter .NET Framework kann TransparentNetworkIPResolution=True (die Standardeinstellung) immer dann zu langen Verbindungsverzögerungen und Timeouts beim Pre-Authentication-Handshake führen, wenn der Ziel-DNS-Name in mehrere IP-Adressen aufgelöst wird und eine der zuerst aufgelösten IP-Adressen fehlerhaft, veraltet oder nicht erreichbar ist. TNIR probiert die aufgelösten IP-Adressen der Reihe nach aus und erhöht in jeder Runde das Timeout pro Versuch, bis insgesamt Connect Timeout erreicht ist. Typischerweise beobachten Sie eine unerwartet lange Verbindungsverzögerung, die mit folgendem Fehler endet:

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.

Das Muster tritt in mehreren Topologien auf:

  • Azure SQL-Datenbank, Azure SQL Managed Instance oder SQL database in Microsoft Fabric. Das Azure SQL-Gateway leitet jede Authentifizierung an ein Backend-Replikat. Wenn eine geroutete Verbindung ausfällt, versucht TNIR erneut, eine Verbindung mit dem gerouteten Backend herzustellen, ohne zum Gateway zurückzukehren, um erneut weitergeleitet zu werden, wodurch sich die Verzögerung während eines Backend-Failovers verlängert.
  • Lokaler SQL Server hinter einem Listener einer Always On-Verfügbarkeitsgruppe, dessen DNS-Name in die IP-Adressen mehrerer Replikate aufgelöst wird. Ein veralteter DNS-Eintrag oder eine ungesunde Replik-IP wird sequentiell ausprobiert, bevor TNIR eine funktionierende Replik erreicht.
  • Failover-Cluster-Instanzen mit einem Multi-Subnet-Cluster-Listener oder einer anderen Konfiguration, bei der der Ziel-DNS-Name mehrere A/AAAA Datensätze hat (wie DNS-Round-Robin).

Um dieses Verhalten zu vermeiden, setze MultiSubnetFailover=True in der Verbindungszeichenfolge:

MultiSubnetFailover=True

Diese Empfehlung funktioniert auf jeder .NET-Version und umfasst sowohl Azure SQL als auch den lokalen SQL Server. Wenn MultiSubnetFailover=True, ignoriert der Treiber TransparentNetworkIPResolution, versucht er die per DNS aufgelösten IP-Adressen parallel und schließt er die Authentifizierung mit der zuerst antwortenden Replik ab. Trotz des Namens MultiSubnetFailover gilt es für jeden Zuhörer, dessen DNS-Name auf mehrere Ziel-IPs aufgelöst wird, unabhängig davon, ob diese IPs sich in verschiedenen Subnetzen befinden, und es ist sicher auf eigenständigen Servern, deren DNS auf eine einzige IP aufgelöst wird.

Um die Steuerung prozessweit vorzunehmen, ohne jede Verbindungszeichenfolge bearbeiten zu müssen, verwenden Sie standardmäßig den AppContext-Schalter Enable MultiSubnetFailover.

Deaktivieren Sie TNIR mit einem AppContext-Schalter

Um den Standardwert von TransparentNetworkIPResolution von von true auf false im .NET Framework umzudrehen, setzen Sie den AppContext-Switch Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString auf true beim Anwendungsstart. Diese Option ändert den Standardwert nur, wenn TransparentNetworkIPResolution nicht in der Verbindungszeichenfolge enthalten ist; ein explizit angegebener Wert wird dadurch nicht überschrieben.

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

Weitere Informationen zum Festlegen dieser Eigenschaften finden Sie in der Dokumentation zur SqlConnection.ConnectionString-Eigenschaft.

Minimales Timeout während der Anmeldung deaktivieren

Gilt für: .NET Framework; .NET; .NET Standard

Standardmäßig erzwingt SqlClient bei der Berechnung der verfügbaren Zeit für einen Anmeldeversuch eine Mindestdauer von einer Sekunde. Dieses Verhalten verhindert, dass ein Login-Versuch unbegrenzt wartet, wenn die berechnete Zeitzeit auf null abgerundet wird.

Um das Legacy-Verhalten wiederherzustellen, setzen Sie den AppContext-Switch Switch.Microsoft.Data.SqlClient.UseOneSecFloorInTimeoutCalculationDuringLogin beim Anwendungsstart auf false:

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

Deaktivieren des blockierenden Verhaltens von ReadAsync

Gilt für: .NET Framework; .NET; .NET Standard

Ab Version 3.0 ReadAsync läuft sie asynchron. Frühere Versionen laufen ReadAsync synchron und blockieren den aufrufenden Thread auf .NET Framework. Um dieses Blockierungsverhalten zu kontrollieren, stellen Sie den AppContext-Schalter Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking auf true oder false beim Anwendungsstart ein:

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

Aktivieren Sie das NULL-Verhalten von rowversion

Gilt für: .NET Framework; .NET; .NET Standard

Ab Version 3.0 gibt eine Rowversion , wenn sie einen Nullwert hat, SqlDataReader einen DBNull Wert statt eines leeren byte[]zurück. Um das Legacyverhalten zu aktivieren, bei dem ein leeres byte[] zurückgegeben wird, aktivieren Sie beim Anwendungsstart den AppContext-Schalter Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior.

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

Unterdrücken von Warnungen zu unsicherem TLS

Gilt für: .NET Framework; .NET; .NET Standard

(Verfügbar ab Version 4.0.1)

Beim Einsatz Encrypt=false im Verbindungszeichenfolge gibt die Konsole eine Sicherheitswarnung aus, wenn die TLS-Version 1.2 oder niedriger ist. Unterdrücken Sie diese Warnung, indem Sie beim AppContext-Start folgenden AppContext-Schalter aktivieren:

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

Ignoriere den vom Server bereitgestellten Failoverpartner

Gilt für: .NET Framework; .NET; .NET Standard

(Ab Version 5.1.8, 6.0.4 und 6.1.3 verfügbar)

Bei einem Failover werden die vom Server bereitgestellten Failover-Partnerinformationen gegenüber den in der Verbindungszeichenfolge angegebenen bevorzugt. Um Failoverpartnerinformationen vom Server zu ignorieren und nur Failoverpartnerinformationen in der Verbindungszeichenfolge zu berücksichtigen, aktivieren Sie diesen AppContext-Switch beim Starten der Anwendung:

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

Erzwingen Sie das Verbindungs-Leerlauf-Timeout

Gilt für: .NET Framework; .NET; .NET Standard

Ab Version 7.1.0 konfigurieren das Connection Idle Timeout-Verbindungszeichenfolgenschlüsselwort und die SqlConnectionStringBuilder.IdleTimeout-Eigenschaft Leerlaufablaufprüfungen und Hintergrundbereinigungen für gepoolte Verbindungen. Die Standardeinstellung ist 300 Sekunden. Negative Werte lösen eine ArgumentException aus.

Die Schalter- und Verbindungszeichenfolge-Einstellungen beeinflussen jede Pool-Implementierung unterschiedlich:

  • V1-Pool. Wenn der Schalter true ist, verwendet V1 den bisherigen zufälligen Bereinigungsrhythmus von zwei bis vier Minuten und entfernt Leerlaufverbindungen unabhängig von Connection Idle Timeout. Wenn der Schalter false und Connection Idle Timeout ungleich null ist, verwendet V1 die Hälfte des konfigurierten Timeouts als Bereinigungsrhythmus und entfernt inaktive Verbindungen nach ein oder zwei Bereinigungszyklen. Wenn der Schalter false und Connection Idle Timeout=0 ist, deaktiviert V1 die Entfernung bei Inaktivität, setzt aber die Wartung der Mindestpoolgröße im historischen zufälligen Zwei- bis Vier-Minuten-Intervall fort.
  • V2-Pool. Wenn der Schalter true ist, führt V2 keine Prüfungen auf Inaktivität/Alter pro Verbindung durch, aber ein Wert ungleich null für Connection Idle Timeout aktiviert und konfiguriert die Hintergrundbereinigung. Wenn der Schalter false ist und Connection Idle Timeout ungleich null, führt V2 Prüfungen auf Inaktivität/Alter pro Verbindung durch und konfiguriert die Hintergrundbereinigung aus dem Timeout. Wenn der Schalter false und Connection Idle Timeout=0 ist, führt V2 keine Prüfungen auf Inaktivität/Alter pro Verbindung oder Hintergrundbereinigung durch. V2 führt keine Hintergrundbereinigung durch, wenn Min Pool Size größer oder gleich Max Pool Size ist.
AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseLegacyIdleTimeoutBehavior", false);

Für Konfigurationsbeispiele siehe Verbindungsleerlaufzeit begrenzen.

Aktivieren Sie den V2-Verbindungspool

Gilt für: .NET Framework; .NET; .NET Standard

Ab Version 7.1 enthält SqlClient eine alternative Connection Pool-Implementierung (V2). Der V1-Pool bleibt der Standard, und der Schalter steht standardmäßig auf false.

Um V2 zu aktivieren, aktivieren Sie den AppContext-Switch Switch.Microsoft.Data.SqlClient.UseConnectionPoolV2 beim Start der Anwendung:

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

Die Steuerelemente für das Verbindungszeichenfolgenpooling gelten für beide Implementierungen. Weitere Informationen finden Sie unter SQL Server Connection Pooling.

Verwenden Sie ein gemeinsames Verbindungs-Timeout für Pool-Wartezeiten und Netzwerkverbindungen

Gilt für: .NET Framework; .NET; .NET Standard

Ab Version 7.1.0 kann die Wartezeit auf eine Verbindung aus dem Pool auf das Connect Timeout Budget des Anrufers angerechnet werden, sodass die Wartezeit im Pool und der Netzwerkverbindungsversuch demselben Gesamt-Timeout unterliegen. Aktivieren Sie Switch.Microsoft.Data.SqlClient.UseOverallConnectTimeoutForPoolWait für die Nutzung des gesamten Timeouts bei beiden Verbindungspool-Implementierungen:

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

Der Schalter ist standardmäßig auf false eingestellt. Dies bewahrt standardmäßig das Legacy-Verhalten bei Verbindungstimeouts, bei dem der Poolvorgang einen vollständigen Connect Timeout und der Netzwerkverbindungsversuch einen weiteren vollständigen Timeout erhält. Infolgedessen können Open oder OpenAsync länger dauern als die konfigurierte Connect Timeout.

Bei Anmeldefehlern zur Legacy-Failover-Alteration zurücksetzen

Gilt für: .NET Framework; .NET; .NET Standard

Ab Version 7.1.0 wechselt SqlClient beim Verbinden mit konfiguriertem Failover nicht mehr zum Failover-Partner, wenn SQL-Fehler während der Anmeldephase zurückgegeben werden. Um zum alten Alternation-Verhalten zurückzuverkehren, aktivieren Sie den AppContext-Switch Switch.Microsoft.Data.SqlClient.UseLegacyFailoverAlternationOnLoginSqlErrors beim Anwendungsstart. Der Schalter ist standardmäßig auf false eingestellt.

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

Respektieren Sie eine explizite Nullskala bei den Variabelzeitparametern

Gilt für: .NET Framework; .NET; .NET Standard

Standardmäßig sendet SqlClient eine Skala von 7, wenn man die Skala explizit auf 0 für Datetime2, Datetimeoffset oder Zeitparameter setzt. Ab Version 6.0 oder höher setzen Sie Switch.Microsoft.Data.SqlClient.LegacyVarTimeZeroScaleBehaviour beim Start der Anwendung auf false, um die explizite Skalierung von 0 beizubehalten. Der Schalter ist standardmäßig auf true eingestellt.

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