Conmutadores de AppContext en SqlClient

Se aplica a: .NET Framework .NET Standard

Descargar ADO.NET

La clase AppContext permite que SqlClient proporcione nueva funcionalidad mientras sigue siendo compatible con los llamadores que dependen del comportamiento anterior. Los usuarios pueden excluirse de un cambio en el comportamiento del sistema configurando interruptores específicos de AppContext.

Habilitar MultiSubnetFailover de forma predeterminada

Se aplica a: .NET Framework; .NET; .NET Standard

(Disponible a partir de la versión 7.0)

Para establecer MultiSubnetFailover=true globalmente sin modificar cadenas de conexión individuales, puede establecer el conmutador AppContext "Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault" en true al inicio de la aplicación.

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

También puede habilitar este interruptor en App.Config.

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

Cuando está habilitada, todas las conexiones se comportan como si MultiSubnetFailover=true estuviera establecida en la cadena de conexión. Este interruptor está deshabilitado de forma predeterminada.

Habilitación de la multiplexación de paquetes para lecturas asincrónicas

Se aplica a: .NET Framework; .NET; .NET Standard

(Disponible a partir de la versión 7.0)

La multiplexación de paquetes mejora el rendimiento de las operaciones de lectura asincrónicas grandes, como ExecuteReaderAsync con grandes conjuntos de resultados, escenarios de streaming o recuperación masiva de datos. Esta característica se controla mediante dos interruptores opcionales de AppContext. Al establecer ambos modificadores en false se habilita la nueva ruta de procesamiento asincrónica:

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

De forma predeterminada, ambos interruptores son true, lo que conserva el comportamiento existente (compatible).

Habilitación de la extensión de características del Agente de usuario

Se aplica a: .NET Framework; .NET; .NET Standard

(Disponible a partir de la versión 7.0)

Cuando el modificador AppContext "Switch.Microsoft.Data.SqlClient.EnableUserAgent" está habilitado, el controlador envía los detalles del agente de usuario al servidor como parte de la conexión. Esta información ayuda a solucionar problemas y cuantificar el uso de controladores por versión y sistema operativo. Este interruptor está deshabilitado de forma predeterminada. Para habilitarlo, establezca el modificador AppContext en true en el inicio de la aplicación:

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

Habilitación del comportamiento de truncamiento decimal

Se aplica a: .NET Framework; .NET; .NET Standard

A partir de Microsoft.Data.SqlClient 2.0, los datos decimales se redondean de forma predeterminada, tal como lo hace SQL Server. Para habilitar el comportamiento previo de truncamiento, puede establecer el modificador de AppContext "Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal" en true al iniciar la aplicación:

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

Habilitación de redes administradas en Windows

Se aplica a: .NET; .NET Standard

(Disponible a partir de la versión 2.0).

En Windows, SqlClient utiliza de forma predeterminada una implementación nativa de la interfaz de red SNI. Para habilitar el uso de una implementación de SNI administrada, puede establecer el modificador de AppContext "Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows" en true en el inicio de la aplicación:

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

Este interruptor alterna el comportamiento del controlador para usar una implementación de red administrada en los proyectos de .NET Core 2.1+ y .NET Standard 2.0+ en Windows, eliminando todas las dependencias de las bibliotecas nativas para la biblioteca Microsoft.Data.SqlClient. Es solo para fines de prueba y depuración.

Nota:

Hay algunas diferencias conocidas en comparación con la implementación nativa. Por ejemplo, la implementación administrada no admite la autenticación de Windows que no sea de dominio.

Desactivación de la resolución de IP de red transparente

Se aplica a: .NET Framework

La Resolución de IP de Red Transparente (TNIR) es una revisión de la característica MultiSubnetFailover existente. TNIR afecta la secuencia de conexión del controlador en el caso de que la primera dirección IP resuelta del nombre del host no responda y haya varias direcciones IP asociadas con el nombre del host. La combinación de TransparentNetworkIPResolution y MultiSubnetFailover selecciona la secuencia de conexión:

TransparentNetworkIPResolution MultiSubnetFailover Secuencia de conexión
Verdadero Verdadero TransparentNetworkIPResolution se pasa por alto. El controlador intenta las direcciones IP resueltas por DNS en paralelo y completa la autenticación con el primer interviniente.
Verdadero Falso El controlador ejecuta varias rondas de conexión a través de las direcciones IP resueltas por DNS, con un mínimo de 500 milisegundos en el primer intento y tiempos de espera progresivamente mayores por intento, hasta que una conexión tiene éxito o se alcanza el total Connect Timeout total.
Falso Verdadero El controlador intenta las direcciones IP resueltas por DNS en paralelo y completa la autenticación con el primer interviniente.
Falso Falso El controlador intenta cada dirección IP resuelta por DNS de forma secuencial hasta que una tenga éxito o Connect Timeout se alcance.

TransparentNetworkIPResolutionestá activado por defecto en .NET Framework y MultiSubnetFailover está deshabilitado por defecto. En .NET 5 y versiones posteriores, TransparentNetworkIPResolution no es una palabra clave de cadena de conexión reconocida y al configurarla (con cualquier valor) se lanza ArgumentException (KeywordNotSupported). Esas versiones solo honor MultiSubnetFailover . El resto de esta sección (la anulación automática, los modos de fallo en la siguiente advertencia y el interruptor AppContext) se aplica al Marco .NET.

Sugerencia

Establecido MultiSubnetFailover=True en cada cadena de conexión, independientemente de la versión .NET o de si el destino es Azure SQL o SQL Server local. MultiSubnetFailover=True selecciona una ruta de código paralela que encuentra rápidamente la primera réplica responsiva. En .NET Framework, también se evita el bucle secuencial de reintentos por IP de TNIR, que es una causa común de largos retrasos de conexión y tiempos de espera de handshake previos a la autenticación.

En .NET Framework, cuando TransparentNetworkIPResolution no se especifica en la cadena de conexión, el controlador desactiva automáticamente TNIR cuando la fuente de datos es un endpoint Azure SQL reconocido, cuando la Authentication clave se establece en cualquier método Microsoft Entra ID (Active Directory Password, Active Directory Integrated, Active Directory Interactive, Active Directory Service PrincipalActive Directory Device Code Flow, Active Directory Managed Identity, Active Directory MSI, Active Directory DefaultActive Directory Workload Identityo ), o cuando la SqlConnection.AccessToken propiedad está establecida. Para los sufijos de endpoint que reconoce el controlador, véase la TransparentNetworkIPResolution entrada en SqlConnection.ConnectionString.

Un valor explícito TransparentNetworkIPResolution evita este comportamiento automático: True activa el TNIR y False desactiva el TNIR incondicionalmente. Para restaurar el comportamiento automático, elimina la palabra clave de la cadena de conexión. La anulación automática tampoco se aplica cuando la cadena de conexión apunta a Azure SQL a través de un CNAME personalizado o un nombre de vanity DNS cuyo sufijo no se reconoce como endpoint de Azure SQL. La anulación automática apunta específicamente a Azure SQL; no se activa para SQL Server local, así que TNIR está activado por defecto allí.

Retrasos largos de conexión en .NET Framework

En el Framework .NET, TransparentNetworkIPResolution=True (el valor predeterminado) puede causar largos retrasos de conexión y tiempos de espera en la preautenticación de la autenticación cada vez que el nombre DNS de destino se resuelve a múltiples IPs y una de las IPs anteriores es inestable, está obsoleta o es inaccesible. TNIR prueba las IPs resueltas secuencialmente y aumenta el tiempo muerto por intento en cada ronda hasta alcanzar el total Connect Timeout . Normalmente observas un retraso de conexión inesperadamente largo que termina en este error:

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.

El patrón aparece en varias topologías:

  • Azure SQL Database, Azure SQL Managed Instance o SQL Database en Microsoft Fabric. La pasarela Azure SQL enruta cada autenticación a una réplica backend. Cuando falla una conexión enrutada, TNIR vuelve a intentar el backend enrutado sin volver a la pasarela para ser redirigido, lo que extiende el retardo durante un backend de conmutación por error.
  • SQL Server local detrás de un oyente de grupo de disponibilidad Always On cuyo nombre DNS se resuelve a múltiples IPs réplica. Una entrada DNS obsoleta o una réplica IP inestable se prueba secuencialmente antes de que TNIR alcance una réplica funcional.
  • Instancias de clúster de conmutación por conmutación por error con un oyente de clúster multi-subred, o cualquier otra configuración donde el nombre DNS de destino tenga múltiples A/AAAA registros (como el sistema de todos en modo round-robin DNS).

Para evitar este comportamiento, se pone MultiSubnetFailover=True en la cadena de conexión:

MultiSubnetFailover=True

Esta recomendación funciona en todas las versiones de .NET y cubre tanto Azure SQL como SQL Server local. Cuando MultiSubnetFailover=True, el controlador ignora TransparentNetworkIPResolution, intenta las direcciones IP resueltas por DNS en paralelo y completa la autenticación con la primera réplica responsiva. A pesar del nombre, MultiSubnetFailover se aplica a cualquier oyente cuyo nombre DNS resuelva a múltiples IPs objetivo, independientemente de si esas IPs están en subredes diferentes, y es seguro en servidores independientes cuyo DNS se resuelve a una sola IP.

Para un control a nivel de proceso sin editar todas las cadena de conexión, utiliza el interruptor AppContext Enable MultiSubnetFailover.

Desactiva TNIR con un interruptor AppContext

Para cambiar el valor por defecto de TransparentNetworkIPResolution de de a false en .NET Framework, configura el interruptor Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString AppContext en true el inicio true de la aplicación. Este switch solo cambia el valor por defecto cuando TransparentNetworkIPResolution no está en la cadena de conexión; no sobreescribe un valor explícito.

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

Para obtener más información sobre cómo establecer estas propiedades, vea la documentación de la Propiedad SqlConnection.ConnectionString.

Habilitación de un tiempo de espera mínimo durante el inicio de sesión

Se aplica a: .NET Framework; .NET; .NET Standard

Para evitar que un intento de inicio de sesión espere indefinidamente, puede establecer el conmutador de AppContext Switch.Microsoft.Data.SqlClient.UseOneSecFloorInTimeoutCalculationDuringLogin en true al inicio de la aplicación.

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

Deshabilitación del comportamiento de bloqueo de ReadAsync

Se aplica a: .NET Framework; .NET; .NET Standard

A partir de la versión 3.0, ReadAsync se ejecuta de forma asincrónica. Las versiones anteriores ejecutan ReadAsync de forma sincrónica y bloquean el subproceso de llamada en .NET Framework. Para controlar este comportamiento de bloqueo, puede establecer el modificador de AppContext Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking en true o false en el inicio de la aplicación:

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

Activación del comportamiento NULL de rowversion

Se aplica a: .NET Framework; .NET; .NET Standard

A partir de la versión 3.0, cuando una versión de fila tiene un valor de NULL, SqlDataReader devuelve un valor DBNull en lugar de un valor byte[] vacío. Para habilitar el comportamiento heredado de devolver un byte[] vacío, habilite el modificador de AppContext Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior al iniciar la aplicación.

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

Ocultar advertencia de TLS inseguro

Se aplica a: .NET Framework; .NET; .NET Standard

(Disponible a partir de la versión 4.0.1).

Cuando se usa Encrypt=false en la cadena de conexión, se genera una advertencia de seguridad en la consola si la versión de TLS es 1.2 o inferior. Esta advertencia se puede suprimir habilitando el siguiente modificador de AppContext en el inicio de la aplicación:

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

Omitir asociado de conmutación por error proporcionado por el servidor

Se aplica a: .NET Framework; .NET; .NET Standard

(Disponible a partir de las versiones 5.1.8, 6.0.4 y 6.1.3)

Tras la conmutación por error, es preferible utilizar la información del asociado de conmutación por error proporcionada por el servidor sobre la proporcionada en la cadena de conexión. Para pasar por alto la información del asociado de conmutación por error proporcionada por el servidor y considerar solo la información del asociado de conmutación por error proporcionada en la cadena de conexión, habilite este modificador AppContext en el inicio de la aplicación:

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

Consulte también

Clase AppContext