Compartir a través de


Introducción al espacio de nombres Microsoft.Data.SqlClient

Descargar ADO.NET

El espacio de nombres Microsoft.Data.SqlClient es básicamente una nueva versión del espacio de nombres System.Data.SqlClient. Microsoft.Data.SqlClient generalmente mantiene la misma API y la misma compatibilidad con System.Data.SqlClient. Migrar de System.Data.SqlClient a Microsoft.Data.SqlClient es sencillo para la mayoría de las aplicaciones. Agregue una dependencia de NuGet en Microsoft.Data.SqlClient y actualice las referencias e instrucciones using a Microsoft.Data.SqlClient.

Hay algunas diferencias en las API menos usadas en comparación con System.Data.SqlClient que pueden afectar a algunas aplicaciones. Acerca de esas diferencias, consulte esta útil hoja de referencia rápida sobre portabilidad.

Referencia de API

Los detalles de la API Microsoft.Data.SqlClient se pueden encontrar en el explorador de la API de .NET.

Notas de la versión de Microsoft.Data.SqlClient 5.2

Nuevas características de la versión 5.2

  • Se ha agregado compatibilidad con SqlDiagnosticListener en .NET Standard. #1931
  • Se ha agregado la nueva propiedad RowsCopied64 a SqlBulkCopy. N.º 2004 Más información
  • Se ha agregado una nueva API AccessTokenCallBack a SqlConnection. N.º 1260 Más información
  • Se ha agregado compatibilidad con la opción de registro SuperSocketNetLib para cifrar en .NET en Windows. #2047
  • Se ha agregado compatibilidad de SqlBatch con .NET 6+ n.º 1825, n.º 2223 Más información
  • Se ha agregado compatibilidad con la autenticación de la identidad de cargas de trabajo #2159, #2264
  • Se ha agregado compatibilidad de localización en .NET #2210
  • Se ha agregado compatibilidad con la intercalación georgiana #2194
  • Se ha agregado compatibilidad con sistemas Big Endian #2170
  • Se ha agregado compatibilidad con .NET 8 #2230
  • Se ha agregado una versión explícita para las principales dependencias de la versión de .NET en System.Runtime.Caching 8.0.0, System.Configuration.ConfigurationManager 8.0.0 y System.Diagnostics.DiagnosticSource 8.0.0 #2303
  • Se ha agregado la capacidad de generar símbolos de depuración en un archivo de paquete independiente #2137

Se ha agregado una nueva propiedad RowsCopied64 a SqlBulkCopy

SqlBulkCopy tiene una nueva propiedad RowsCopied64 que admite long tipos de valor.

Tenga en cuenta que el comportamiento SqlBulkCopy.RowsCopied existente no cambia. Cuando el valor supera int.MaxValue, RowsCopied puede devolver un número negativo.

Ejemplo de uso:

    using (SqlConnection srcConn = new SqlConnection(srcConstr))
    using (SqlCommand srcCmd = new SqlCommand("select top 5 * from employees", srcConn))
    {
        srcConn.Open();
        using (DbDataReader reader = srcCmd.ExecuteReader())
        {
            using (SqlBulkCopy bulkcopy = new SqlBulkCopy(dstConn))
            {
                bulkcopy.DestinationTableName = dstTable;
                SqlBulkCopyColumnMappingCollection ColumnMappings = bulkcopy.ColumnMappings;

                ColumnMappings.Add("EmployeeID", "col1");
                ColumnMappings.Add("LastName", "col2");
                ColumnMappings.Add("FirstName", "col3");

                bulkcopy.WriteToServer(reader);
                long rowsCopied = bulkcopy.RowsCopied64;
            }
        }
    }

Se ha agregado una nueva propiedad AccessTokenCallBack a SqlConnection

SqlConnection admite la autenticación TokenCredential mediante la introducción de una nueva propiedad AccessTokenCallBack como delegado de Func<SqlAuthenticationParameters, CancellationToken,Task<SqlAuthenticationToken>> para devolver un token de acceso de autenticación federada.

Ejemplo de uso:

using Microsoft.Data.SqlClient;
using Azure.Identity;

const string defaultScopeSuffix = "/.default";
string connectionString = GetConnectionString();
DefaultAzureCredential credential = new();
using SqlConnection connection = new(connectionString);

connection.AccessTokenCallback = async (authParams, cancellationToken) =>
{
    string scope = authParams.Resource.EndsWith(defaultScopeSuffix)
        ? authParams.Resource
        : $"{authParams.Resource}{defaultScopeSuffix}";
    AccessToken token = await cred.GetTokenAsync(
        new TokenRequestContext([scope]),
        cancellationToken);

    return new SqlAuthenticationToken(token.Token, token.ExpiresOn);
}

connection.Open();
Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
Console.WriteLine("State: {0}", connection.State);

API SqlBatch

Ejemplo de uso:

using Microsoft.Data.SqlClient;

class Program
{
    static void Main()
    {
        string str = "Data Source=(local);Initial Catalog=Northwind;"
        + "Integrated Security=SSPI;Encrypt=False";
        RunBatch(str);
    }

    static void RunBatch(string connString)
    {
        using var connection = new SqlConnection(connString);
        connection.Open();

        var batch = new SqlBatch(connection);

        const int count = 10;
        const string parameterName = "parameter";
        for (int i = 0; i < count; i++)
        {
            var batchCommand = new SqlBatchCommand($"SELECT @{parameterName} as value");
            batchCommand.Parameters.Add(new SqlParameter(parameterName, i));
            batch.BatchCommands.Add(batchCommand);
        }

        // Optionally Prepare
        batch.Prepare();

        var results = new List<int>(count);
        using (SqlDataReader reader = batch.ExecuteReader())
        {
            do
            {
                while (reader.Read())
                {
                    results.Add(reader.GetFieldValue<int>(0));
                }
            } while (reader.NextResult());
        }
        Console.WriteLine(string.Join(", ", results));
    }
}

Compatibilidad con la plataforma de destino 5.2

  • .NET Framework 4.6.2+ (Windows x86, Windows x64)
  • .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)

Las notas de la versión completas, incluidas las dependencias, están disponibles en el repositorio de GitHub de las notas de la versión 5.2.

Cambios importantes en la versión 5.1

Nuevas características de la versión 5.1

  • Se ha agregado compatibilidad con DateOnly y TimeOnly para el valor de SqlParameter y GetFieldValue. #1813
  • Se ha agregado compatibilidad con TLS 1.3 para .NET Core y SNI Native. #1821
  • Se ha agregado la configuración de ServerCertificate para Encrypt=Mandatory o Encrypt=Strict. N.º 1822 Más información
  • Se ha agregado compatibilidad con Windows ARM64 al establecer como destino .NET Framework. #1828

Certificado de servidor

El valor predeterminado de la configuración de conexión de ServerCertificate es una cadena vacía. Cuando se establece Encrypt en Mandatory o Strict, se puede usar ServerCertificate para especificar una ruta de acceso en el sistema de archivos a un archivo de certificado para coincidir con el certificado TLS/SSL del servidor. El certificado especificado debe ser una coincidencia exacta para que sea válido. Los formatos de certificado permitidos son PEM, DER y CER. Presentamos un ejemplo de uso:

"Data Source=...;Encrypt=Strict;ServerCertificate=C:\\certificates\\server.cer"

Compatibilidad con la plataforma de destino 5.1

  • .NET Framework 4.6.2+ (Windows x86, Windows x64)
  • .NET 6.0+ (Windows x86, Windows x64, Windows ARM64, Windows Azure Resource Manager, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)

Las notas de la versión completas, incluidas las dependencias, están disponibles en el repositorio de GitHub de las notas de la versión 5.1.

Notas de la versión de Microsoft.Data.SqlClient 5.0

Cambios importantes en la versión 5.0

  • Se ha quitado la compatibilidad con .NET Framework 4.6.1. #1574.
  • Se ha agregado una dependencia en el paquete Microsoft.SqlServer.Server. Esta nueva dependencia puede provocar conflictos de espacio de nombres si la aplicación hace referencia a ese espacio de nombres y sigue teniendo referencias de paquete (directas o indirectas) a System.Data.SqlClient desde .NET Core.
  • Se han quitado las clases del espacio de nombres Microsoft.Data.SqlClient.Server y se han reemplazado por tipos admitidos del paquete Microsoft.SqlServer.Server. #1585. Las clases y enumeraciones afectadas son:
    • Microsoft.Data.SqlClient.Server.IBinarySerialize -> Microsoft.SqlServer.Server.IBinarySerialize
    • Microsoft.Data.SqlClient.Server.InvalidUdtException -> Microsoft.SqlServer.Server.InvalidUdtException
    • Microsoft.Data.SqlClient.Server.SqlFacetAttribute -> Microsoft.SqlServer.Server.SqlFacetAttribute
    • Microsoft.Data.SqlClient.Server.SqlFunctionAttribute -> Microsoft.SqlServer.Server.SqlFunctionAttribute
    • Microsoft.Data.SqlClient.Server.SqlMethodAttribute -> Microsoft.SqlServer.Server.SqlMethodAttribute
    • Microsoft.Data.SqlClient.Server.SqlUserDefinedAggregateAttribute -> Microsoft.SqlServer.Server.SqlUserDefinedAggregateAttribute
    • Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute -> Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute
    • (enum) Microsoft.Data.SqlClient.Server.DataAccessKind -> Microsoft.SqlServer.Server.DataAccessKind
    • (enum) Microsoft.Data.SqlClient.Server.Format -> Microsoft.SqlServer.Server.Format
    • (enum) Microsoft.Data.SqlClient.Server.SystemDataAccessKind -> Microsoft.SqlServer.Server.SystemDataAccessKind

Nuevas características de la versión 5.0

  • Se ha agregado compatibilidad con TDS8. Para usar TDS 8, los usuarios deben especificar Encrypt=Strict en la cadena de conexión. N.º 1608 Más información
  • Se ha agregado funcionalidad para especificar el SPN del servidor y el SPN del servidor de conmutación por error en la conexión. N.º 1607 Más información
  • Se ha agregado compatibilidad con alias al establecer .NET Core en Windows como destino. N.º 1588 Más información
  • Se ha agregado SqlDataSourceEnumerator. #1430. Más información
  • Se ha agregado un nuevo modificador AppContext para suprimir las advertencias de TLS no seguras. #1457. Más información

Seguridad mejorada en TDS 8

Para usar TDS 8, especifique Encrypt=Strict en la cadena de conexión. El modo strict deshabilita TrustServerCertificate (tratado siempre como False en el modo strict). Se ha agregado HostNameInCertificate para ayudar en algunos escenarios del modo strict. TDS 8 comienza y continúa toda la comunicación del servidor en una conexión TLS cifrada segura.

Se han agregado nuevos valores de Encrypt para aclarar el comportamiento del cifrado de la conexión. Encrypt=Mandatory equivale a Encrypt=True y cifra las conexiones durante la negociación de conexión de TDS. Encrypt=Optional equivale a Encrypt=False y solo cifra la conexión si el servidor indica al cliente que el cifrado es necesario durante la negociación de la conexión de TDS.

Para más información sobre el cifrado de conexiones al servidor, consulte Cifrado y validación de certificados.

HostNameInCertificate se puede especificar en la cadena de conexión cuando se usan alias para conectarse con cifrado a un servidor que tenga un certificado de servidor con un nombre diferente o un nombre de sujeto alternativo al nombre usado por el cliente para identificar el servidor (alias DNS, por ejemplo). Ejemplo de uso: HostNameInCertificate=MyDnsAliasName

Dirección SPN del servidor

Al conectarse en un entorno que tiene una topografía de dominio/bosque única, es posible que tenga requisitos específicos para los SPN de servidor. La configuración de la cadena de conexión ServerSPN/SPN del servidor y FailoverServerSPN/SPN del servidor de conmutación por error se puede usar para invalidar los SPN de servidor generados automáticamente que se usan durante la autenticación integrada en un entorno de dominio.

Compatibilidad con alias de SQL

Los usuarios pueden configurar alias con el Administrador de configuración de SQL Server. Estos alias se almacenan en el Registro de Windows y ya se admiten cuando el destino es .NET Framework. Esta versión ofrece compatibilidad con alias cuando se establecen .NET o .NET Core en Windows como destino.

Compatibilidad con el enumerador de orígenes de datos de SQL

Proporciona un mecanismo para enumerar todas las instancias disponibles de SQL Server incluidas en la red local.

using Microsoft.Data.Sql;
static void Main()  
  {  
    // Retrieve the enumerator instance and then the data.  
    SqlDataSourceEnumerator instance =  
      SqlDataSourceEnumerator.Instance;  
    System.Data.DataTable table = instance.GetDataSources();  
  
    // Display the contents of the table.  
    DisplayData(table);  
  
    Console.WriteLine("Press any key to continue.");  
    Console.ReadKey();  
  }  
  
  private static void DisplayData(System.Data.DataTable table)  
  {  
    foreach (System.Data.DataRow row in table.Rows)  
    {  
      foreach (System.Data.DataColumn col in table.Columns)  
      {  
        Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);  
      }  
      Console.WriteLine("============================");  
    }  
  }  

Supresión de advertencias de TLS no seguro

Cuando se usa una versión de TLS inferior a la 1.2 para negociar con el servidor, se muestra una advertencia de seguridad en la consola. Esta advertencia se puede suprimir en la conexión de SQL cuando Encrypt = false habilitando el siguiente modificador de AppContext en el inicio de la aplicación:

Switch.Microsoft.Data.SqlClient.SuppressInsecureTLSWarning

Compatibilidad con la plataforma de destino 5.0

  • .NET Framework 4.6.2+ (Windows x86, Windows x64)
  • .NET Core 3.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)

Las notas de la versión completas, incluidas las dependencias, están disponibles en el repositorio de GitHub de las notas de la versión 5.0.

Notas de la versión de Microsoft.Data.SqlClient 4.1

Las notas completas de la versión, incluidas las dependencias, están disponibles en el repositorio de GitHub: Notas de la versión 4.1.

Nuevas características de la versión 4.1

Introducción al protocolo de atestación Ninguno

Se permite un nuevo protocolo de atestación denominado None en la cadena de conexión. Este protocolo permite a los usuarios renunciar a la atestación de enclave para los enclaves VBS. Cuando se establece este protocolo, la propiedad URL de atestación de enclave es opcional.

Ejemplo de cadena de conexión:

//Attestation protocol NONE with no URL
"Data Source = {server}; Initial Catalog = {db}; Column Encryption Setting = Enabled; Attestation Protocol = None;"

Compatibilidad con la plataforma de destino 4.1

  • .NET Framework 4.6.1+ (Windows x86, Windows x64)
  • .NET Core 3.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)

Notas de la versión de Microsoft.Data.SqlClient 4.0

Las notas completas de la versión, incluidas las dependencias, están disponibles en el repositorio de GitHub: Notas de la versión 4.0.

Cambios importantes en la versión 4.0

  • Se ha cambiado la propiedad existente de cadena de conexión Encrypt a true de manera predeterminada. N.º 1210 Más información
  • El controlador ahora inicia SqlException que sustituye AggregateException de los modos de autenticación de Active Directory. N.º 1213
  • Se ha eliminado la propiedad de conexión Asynchronous Processing obsoleta de .NET Framework. N.º 1148
  • Se ha quitado el conmutador de seguridad Configurable Retry Logic. N.º 1254 Más información
  • Se ha eliminado la compatibilidad con .NET Core 2.1 N.º 1272.
  • [.NET Framework] No se produce una excepción si se proporciona un identificador de usuario en la cadena de conexión cuando se usa la autenticación de Active Directory Integrated#1359

Nuevas características de la versión 4.0

Cifrado del valor predeterminado establecido en true

El valor predeterminado de la configuración de conexión Encrypt se ha cambiado de false a true. Con el creciente uso de las bases de datos en la nube y la necesidad de garantizar que esas conexiones sean seguras, ha llegado el momento de este cambio importante de compatibilidad con versiones anteriores.

Asegurarse de que las conexiones no se pueden realizar cuando se requiere cifrado

En escenarios en los que las bibliotecas de cifrado de cliente estaban deshabilitadas o no estaban disponibles, era posible realizar conexiones sin cifrar cuando Encrypt se estableció en true o el servidor requería cifrado.

Cambio de contexto de aplicación para usar los protocolos predeterminados del sistema

El controlador no admite TLS 1.3; por tanto, se ha quitado de la lista de protocolos admitidos de forma predeterminada. Los usuarios pueden volver a forzar el uso de los protocolos de cliente del sistema operativo, habilitando el cambio de contexto de aplicación a continuación:

Switch.Microsoft.Data.SqlClient.UseSystemDefaultSecureProtocols

Habilitación del enlace de parámetros optimizados

Microsoft.Data.SqlClient presenta una nueva API SqlCommand, EnableOptimizedParameterBinding, para mejorar el rendimiento de las consultas con un gran número de parámetros. Esta propiedad está deshabilitada de forma predeterminada. Si se establece en true, los nombres de parámetro no se envían a la instancia de SQL Server cuando se ejecuta el comando.

public class SqlCommand
{
    public bool EnableOptimizedParameterBinding { get; set; }
}

Eliminación del conmutador de seguridad lógica de reintento configurable

El cambio de contexto de aplicación "Switch.Microsoft.Data.SqlClient.EnableRetryLogic" ya no es necesario para usar la característica lógica de reintento configurable. La característica ahora se admite en producción. El comportamiento predeterminado de la característica seguirá siendo una directiva sin reintentos, que las aplicaciones cliente tendrán que invalidar para habilitar los reintentos.

Compatibilidad con instancias compartidas de SqlLocalDb

Ahora se admiten instancias compartidas de SqlLocalDb cuando se usa SNI administrado.

  • Escenarios posibles:
    • (localdb)\. (se conecta a la instancia predeterminada de SqlLocalDb)
    • (localdb)\<named instance>
    • (localdb)\.\<shared instance name> (*compatibilidad recién agregada)

Compatibilidad con GetFieldValueAsync<T> y GetFieldValue<T> para los tipos XmlReader, TextReader, Stream

Ahora se admiten los tipos XmlReader, TextReader, Stream al usar GetFieldValueAsync<T> y GetFieldValue<T>.

Ejemplo de uso:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    using (SqlCommand command = new SqlCommand(query, connection))
    {
        connection.Open();
        using (SqlDataReader reader = await command.ExecuteReaderAsync())
        {
            if (await reader.ReadAsync())
            {
                using (Stream stream = await reader.GetFieldValueAsync<Stream>(1))
                {
                    // Continue to read from stream
                }
            }
        }
    }
}

Compatibilidad con la plataforma de destino 4.0

  • .NET Framework 4.6.1+ (Windows x86, Windows x64)
  • .NET Core 3.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)

Notas de la versión de Microsoft.Data.SqlClient 3.0

Las notas completas de la versión, incluidas las dependencias, están disponibles en el repositorio de GitHub: Notas de la versión 3.0.

Cambios importantes en la versión 3.0

  • La versión de .NET Framework mínima admitida ha aumentado a v4.6.1. .NET Framework v4.6.0 ya no se admite. N.º 899.
  • La propiedad de conexión User Id ahora requiere Client Id en lugar de Object Id para la identidad administrada asignada por el usuario. N.º 1010. Más información.
  • SqlDataReader ahora devuelve un valor DBNull en lugar de un byte[] vacío. El comportamiento heredado se puede habilitar mediante el establecimiento del modificador AppContext Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior. N.º 998. Más información.

Nuevas características de la versión 3.0

Lógica de reintento configurable

Esta nueva característica introduce compatibilidad configurable para que las aplicaciones cliente vuelvan a intentar errores "transitorios" o "recuperables". La configuración se puede realizar mediante archivos de configuración de aplicación o código y se pueden aplicar operaciones de reintento para abrir una conexión o ejecutar un comando. Esta característica está deshabilitada de forma predeterminada y se encuentra actualmente en versión preliminar. Para habilitar esta compatibilidad, las aplicaciones cliente deben activar el siguiente modificador de seguridad:

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

Una vez que se ha habilitado el modificador AppContext de .NET, se puede definir una directiva lógica de reintentos para SqlConnection y SqlCommand de forma independiente, o en conjunto mediante varias opciones de personalización.

Se han introducido nuevas API públicas en SqlConnection y SqlCommand para registrar una implementación de SqlRetryLogicBaseProvider personalizada:

public SqlConnection
{
    public SqlRetryLogicBaseProvider RetryLogicProvider;
}

public SqlCommand
{
    public SqlRetryLogicBaseProvider RetryLogicProvider;
}

Aquí encontrará ejemplos de uso de API: .

using Microsoft.Data.SqlClient;

/// Detecting retriable exceptions is a vital part of the retry pattern.
/// Before applying retry logic it is important to investigate exceptions and choose a retry provider that best fits your scenario.
/// First, log your exceptions and find transient faults.
/// The purpose of this sample is to illustrate how to use this feature and the condition might not be realistic.
class RetryLogicSample
{
    private const string DefaultDB = "Northwind";
    private const string CnnStringFormat = "Server=localhost; Initial Catalog={0}; Integrated Security=true; pooling=false;";
    private const string DropDatabaseFormat = "DROP DATABASE {0}";

    // For general use
    private static SqlConnection s_generalConnection = new SqlConnection(string.Format(CnnStringFormat, DefaultDB));

    static void Main(string[] args)
    {
        // 1. Define the retry logic parameters
        var options = new SqlRetryLogicOption()
        {
            NumberOfTries = 5,
            MaxTimeInterval = TimeSpan.FromSeconds(20),
            DeltaTime = TimeSpan.FromSeconds(1)
        };

        // 2. Create a retry provider
        var provider = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options);

        // define the retrying event to report the execution attempts
        provider.Retrying += (object s, SqlRetryingEventArgs e) =>
            {
                int attempts = e.RetryCount + 1;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"attempt {attempts} - current delay time:{e.Delay} \n");
                Console.ForegroundColor = ConsoleColor.DarkGray;
                if (e.Exceptions[e.Exceptions.Count - 1] is SqlException ex)
                {
                    Console.WriteLine($"{ex.Number}-{ex.Message}\n");
                }
                else
                {
                    Console.WriteLine($"{e.Exceptions[e.Exceptions.Count - 1].Message}\n");
                }

                // It is not a good practice to do time-consuming tasks inside the retrying event which blocks the running task.
                // Use parallel programming patterns to mitigate it.
                if (e.RetryCount == provider.RetryLogic.NumberOfTries - 1)
                {
                    Console.WriteLine("This is the last chance to execute the command before throwing the exception.");
                    Console.WriteLine("Press Enter when you're ready:");
                    Console.ReadLine();
                    Console.WriteLine("continue ...");
                }
            };

        // Open the general connection.
        s_generalConnection.Open();

        try
        {
            // Assume the database is being created and other services are going to connect to it.
            RetryConnection(provider);
        }
        catch
        {
            // exception is thrown if connecting to the database isn't successful.
            throw;
        }
    }

    private static void ExecuteCommand(SqlConnection cn, string command)
    {
        using var cmd = cn.CreateCommand();
        cmd.CommandText = command;
        cmd.ExecuteNonQuery();
    }

    private static void RetryConnection(SqlRetryLogicBaseProvider provider)
    {
        // Change this if you already have a database with the same name in your database.
        string dbName = "Invalid_DB_Open";

        // Create a connection to an invalid database.
        using var cnn = new SqlConnection(string.Format(CnnStringFormat, dbName));
        // 3. Assign the `provider` to the connection
        cnn.RetryLogicProvider = provider;
        Console.WriteLine($"Connecting to the [{dbName}] ...");
        // Manually execute the following command in SSMS to create the invalid database while the SqlConnection is attempting to connect to it.
        // >> CREATE DATABASE Invalid_DB_Open;
        Console.WriteLine($"Manually, run the 'CREATE DATABASE {dbName};' in the SQL Server before exceeding the {provider.RetryLogic.NumberOfTries} attempts.");
        // the connection tries to connect to the database 5 times
        Console.WriteLine("The first attempt, before getting into the retry logic.");
        cnn.Open();
        Console.WriteLine($"Connected to the [{dbName}] successfully.");

        cnn.Close();

        // Drop it after test
        ExecuteCommand(s_generalConnection, string.Format(DropDatabaseFormat, dbName));
        Console.WriteLine($"The [{dbName}] is removed.");
    }
}
/// Detecting retriable exceptions is a vital part of the retry pattern.
/// Before applying retry logic it is important to investigate exceptions and choose a retry provider that best fits your scenario.
/// First, log your exceptions and find transient faults.
/// The purpose of this sample is to illustrate how to use this feature and the condition might not be realistic.

    private const string DefaultDB = "Northwind";
    private const string CnnStringFormat = "Server=localhost; Initial Catalog={0}; Integrated Security=true; pooling=false;";
    private const string DropDatabaseFormat = "DROP DATABASE {0}";
    private const string CreateDatabaseFormat = "CREATE DATABASE {0}";

    // For general use
    private static SqlConnection s_generalConnection = new SqlConnection(string.Format(CnnStringFormat, DefaultDB));

    static void Main(string[] args)
    {
        // 1. Define the retry logic parameters
        var options = new SqlRetryLogicOption()
        {
            NumberOfTries = 5,
            MaxTimeInterval = TimeSpan.FromSeconds(20),
            DeltaTime = TimeSpan.FromSeconds(1),
            AuthorizedSqlCondition = null,
            // error number 3702 : Cannot drop database "xxx" because it is currently in use.
            TransientErrors = new int[] {3702}
        };

        // 2. Create a retry provider
        var provider = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options);

        // define the retrying event to report execution attempts
        provider.Retrying += (object s, SqlRetryingEventArgs e) =>
            {
                int attempts = e.RetryCount + 1;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"attempt {attempts} - current delay time:{e.Delay} \n");
                Console.ForegroundColor = ConsoleColor.DarkGray;
                if (e.Exceptions[e.Exceptions.Count - 1] is SqlException ex)
                {
                    Console.WriteLine($"{ex.Number}-{ex.Message}\n");
                }
                else
                {
                    Console.WriteLine($"{e.Exceptions[e.Exceptions.Count - 1].Message}\n");
                }

                // It is not good practice to do time-consuming tasks inside the retrying event which blocks the running task.
                // Use parallel programming patterns to mitigate it.
                if (e.RetryCount == provider.RetryLogic.NumberOfTries - 1)
                {
                    Console.WriteLine("This is the last chance to execute the command before throwing the exception.");
                    Console.WriteLine("Press Enter when you're ready:");
                    Console.ReadLine();
                    Console.WriteLine("continue ...");
                }
            };

        // Open a general connection.
        s_generalConnection.Open();

        try
        {
            // Assume the database is creating and other services are going to connect to it.
            RetryCommand(provider);
        }
        catch
        {
            s_generalConnection.Close();
            // exception is thrown if connecting to the database isn't successful.
            throw;
        }
        s_generalConnection.Close();
    }

    private static void ExecuteCommand(SqlConnection cn, string command)
    {
        using var cmd = cn.CreateCommand();
        cmd.CommandText = command;
        cmd.ExecuteNonQuery();
    }

    private static void FindActiveSessions(SqlConnection cnn, string dbName)
    {
        using var cmd = cnn.CreateCommand();
        cmd.CommandText = "DECLARE @query NVARCHAR(max) = '';" + Environment.NewLine +
            $"SELECT @query = @query + 'KILL ' + CAST(spid as varchar(50)) + ';' FROM sys.sysprocesses WHERE dbid = DB_ID('{dbName}')" + Environment.NewLine +
            "SELECT @query AS Active_sessions;";
        var reader = cmd.ExecuteReader();
        if (reader.Read())
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write($">> Execute the '{reader.GetString(0)}' command in SQL Server to unblock the running task.");
            Console.ResetColor();
        }
        reader.Close();
    }
var RetryLogicOption = new SqlRetryLogicOption()
{
    NumberOfTries = 5,
    // Declare the error number 102 as a transient error to apply the retry logic when it occurs.
    TransientErrors = new int[] { 102 },
    // When a SqlCommand executes out of a transaction, 
    // the retry logic will apply if it contains a 'select' keyword.
    AuthorizedSqlCondition = x => string.IsNullOrEmpty(x)
            || Regex.IsMatch(x, @"\b(SELECT)\b", RegexOptions.IgnoreCase),
    DeltaTime = TimeSpan.FromSeconds(1),
    MaxTimeInterval = TimeSpan.FromSeconds(60),
    MinTimeInterval = TimeSpan.FromSeconds(3)
};

También se han introducido nuevas secciones de configuración para realizar el mismo registro desde los archivos de configuración, sin necesidad de modificar el código existente:

<section name="SqlConfigurableRetryLogicConnection"
            type="Microsoft.Data.SqlClient.SqlConfigurableRetryConnectionSection, Microsoft.Data.SqlClient"/>

<section name="SqlConfigurableRetryLogicCommand"
            type="Microsoft.Data.SqlClient.SqlConfigurableRetryCommandSection, Microsoft.Data.SqlClient"/>

Este es un ejemplo sencillo del uso de las nuevas secciones de configuración en los archivos de configuración:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="SqlConfigurableRetryLogicConnection"
             type="Microsoft.Data.SqlClient.SqlConfigurableRetryConnectionSection, Microsoft.Data.SqlClient"/>
    <section name="SqlConfigurableRetryLogicCommand"
             type="Microsoft.Data.SqlClient.SqlConfigurableRetryCommandSection, Microsoft.Data.SqlClient"/>

    <section name="AppContextSwitchOverrides"
             type="Microsoft.Data.SqlClient.AppContextSwitchOverridesSection, Microsoft.Data.SqlClient"/>
  </configSections>

  <!--Enable safety switch in .NET Core-->
  <AppContextSwitchOverrides value="Switch.Microsoft.Data.SqlClient.EnableRetryLogic=true"/>

  <!--Retry method for SqlConnection-->
  <SqlConfigurableRetryLogicConnection retryMethod ="CreateFixedRetryProvider" numberOfTries ="3" deltaTime ="00:00:10" maxTime ="00:00:30"
                                    transientErrors="40615" />

  <!--Retry method for SqlCommand containing SELECT queries-->
  <SqlConfigurableRetryLogicCommand retryMethod ="CreateIncrementalRetryProvider" numberOfTries ="5" deltaTime ="00:00:10" maxTime ="00:01:10"
                                    authorizedSqlCondition="\b(SELECT)\b" transientErrors="102, 4060, 0"/>
</configuration>

Como alternativa, las aplicaciones pueden implementar su propio proveedor de la clase base SqlRetryLogicBaseProvider y registrarlo con SqlConnection/SqlCommand.

Contadores de eventos

Ahora están disponibles los siguientes contadores para las aplicaciones que tienen como destino .NET Core 3.1+ y .NET Standard 2.1+:

NOMBRE Nombre para mostrar Descripción
active-hard-connections Conexiones activas reales realizadas actualmente a servidores Número de conexiones que están abiertas actualmente a servidores de bases de datos.
hard-connects Velocidad de conexión real a los servidores Número de conexiones por segundo que se abren a servidores de bases de datos.
hard-disconnects Velocidad de desconexión real de los servidores Número de desconexiones por segundo que se producen con servidores de bases de datos.
active-soft-connects Conexiones activas recuperadas del grupo de conexiones Número de conexiones ya abiertas que se consumen desde el grupo de conexiones.
soft-connects Velocidad de las conexiones recuperadas del grupo de conexiones Número de conexiones por segundo que se consumen desde el grupo de conexiones.
soft-disconnects Velocidad de las conexiones recuperadas del grupo de conexiones Número de conexiones por segundo que se devuelven al grupo de conexiones.
number-of-non-pooled-connections Número de conexiones que no usan la agrupación de conexiones Número de conexiones activas que no están agrupadas.
number-of-pooled-connections Número de conexiones administradas por el grupo de conexiones El número de conexiones activas que administra la infraestructura de agrupación de conexiones.
number-of-active-connection-pool-groups Número de cadenas de conexión únicas activas Número de grupos de conexiones activos y únicos. Este contador depende del número de cadenas de conexión única que haya en el dominio de aplicación.
number-of-inactive-connection-pool-groups Número de cadenas de conexión únicas a la espera de ser eliminadas El número de conjuntos de grupos de conexiones únicas marcados para ser eliminados. Este contador depende del número de cadenas de conexión única que haya en el dominio de aplicación.
number-of-active-connection-pools Número de grupos de conexiones activas El número total de grupos de conexiones.
number-of-inactive-connection-pools Número de grupos de conexiones inactivas Número de grupos de conexiones inactivas sin actividad reciente y en espera de ser eliminadas.
number-of-active-connections Número de conexiones activas Número de conexiones actualmente en uso.
number-of-free-connections Número de conexiones listas en el grupo de conexiones Número de conexiones abiertas que se pueden usar en los grupos de conexiones.
number-of-stasis-connections Número de conexiones actualmente a la espera de estar listas Número de conexiones actualmente a la espera de la finalización de una acción y que no están disponibles para su uso por parte de la aplicación.
number-of-reclaimed-connections Número de conexiones reclamadas desde la recolección de elementos no utilizados Número de conexiones que se han reclamado mediante la recolección de elementos no utilizados en las que la aplicación no llamó a Close ni a Dispose. Nota: No cerrar o eliminar explícitamente las conexiones afecta el rendimiento.

Estos contadores se pueden usar con las herramientas de la CLI global de .NET Core: dotnet-counters y dotnet-trace en Windows o Linux y PerfView en Windows, con Microsoft.Data.SqlClient.EventSource como nombre del proveedor. Para obtener más información, vea Recuperación de valores del contador de eventos.

dotnet-counters monitor Microsoft.Data.SqlClient.EventSource -p
PerfView /onlyProviders=*Microsoft.Data.SqlClient.EventSource:EventCounterIntervalSec=1 collect

Introducción a la dependencia de Azure Identity

Microsoft.Data.SqlClient ahora depende de la biblioteca Azure.Identity para adquirir tokens para los modos de autenticación "Identidad administrada de Active Directory/MSI" y "Entidad de servicio de Active Directory". Este cambio conlleva los cambios siguientes en el área expuesta pública:

  • Cambio importante
    La propiedad de conexión "User Id" ahora requiere "Client Id" en lugar de Object Id" para la "Identidad administrada asignada por el usuario".
  • API pública
    Nueva propiedad pública de solo lectura: SqlAuthenticationParameters.ConnectionTimeout
  • Dependencia
    Azure.Identity v1.3.0

Mejoras de seguimiento de eventos en SNI.dll

Las versiones de Microsoft.Data.SqlClient.SNI (dependencia de .NET Framework) y Microsoft.Data.SqlClient.SNI.runtime (dependencia de .NET Core/Standard) se han actualizado a v3.0.0-preview1.21104.2. El seguimiento de eventos en SNI.dll ya no se habilita mediante una aplicación cliente. Basta con la suscripción de una sesión al proveedor Microsoft.Data.SqlClient.EventSource mediante herramientas como xperf o perfview. Para obtener más información, vea Compatibilidad con el seguimiento de eventos en SNI nativo.

Habilitación del comportamiento null de la versión de fila

SqlDataReader devuelve un valor DBNull en lugar de un byte[] vacío. Para habilitar el comportamiento heredado, debe habilitar el siguiente modificador de AppContext al iniciar la aplicación: "Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior" .

Compatibilidad con la autenticación predeterminada de Microsoft Entra

Nota:

Aunque Microsoft Entra ID es el nuevo nombre de Azure Active Directory (Azure AD), para evitar interrumpir los entornos existentes, Azure AD sigue estando en algunos elementos codificados de forma rígida como campos de interfaz de usuario, proveedores de conexiones, códigos de error y cmdlets. En este artículo, los dos nombres son intercambiables.

Esta solicitud de incorporación de cambios introduce un nuevo método de autenticación SQL: Valor predeterminado de Active Directory. Este modo de autenticación aumenta las posibilidades de autenticación del usuario con Microsoft Entra ID, ya que amplía las soluciones de inicio de sesión al entorno de cliente, Visual Studio Code, Visual Studio, la CLI de Azure, etc.

Con este modo de autenticación, el controlador adquiere un token al pasar "DefaultAzureCredential" desde la biblioteca Azure Identity para adquirir un token de acceso. Este modo intenta usar estos tipos de credenciales para adquirir un token de acceso en el orden siguiente:

  • EnvironmentCredential
    • Habilita la autenticación para Microsoft Entra ID mediante el cliente y el secreto, o el nombre de usuario y la contraseña, y los detalles configurados en las siguientes variables de entorno: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_CLIENT_CERTIFICATE_PATH, AZURE_USERNAME y AZURE_PASSWORD (más información)
  • ManagedIdentityCredential
    • Intenta la autenticación de Microsoft Entra ID mediante una identidad administrada que se ha asignado al entorno de implementación. El valor "Id. de cliente" de la "identidad administrada asignada por el usuario" se lee desde la propiedad de conexión "Id. de usuario".
  • SharedTokenCacheCredential
    • Realiza la autenticación mediante tokens en la caché local compartida entre aplicaciones de Microsoft.
  • VisualStudioCredential
    • Permite la autenticación con Microsoft Entra ID mediante los datos de Visual Studio
  • VisualStudioCodeCredential
    • Permite la autenticación con Microsoft Entra ID mediante los datos de Visual Studio Code.
  • AzureCliCredential
    • Habilita la autenticación con Microsoft Entra ID mediante la CLI de Azure para obtener un token de acceso.

InteractiveBrowserCredential está deshabilitado en la implementación del controlador de "Valor predeterminado de Active Directory", y "Active Directory interactivo" es la única opción disponible para adquirir un token mediante MFA o la autenticación interactiva.*

Por el momento, no hay más opciones de personalización disponibles.

Mejoras en el registro de proveedores personalizados de almacén de claves maestras

Microsoft.Data.SqlClient ahora permite controlar mejor dónde se puede acceder a los proveedores de almacén de claves maestras en una aplicación, con el fin de admitir mejor las aplicaciones multiinquilino y su uso del cifrado y descifrado de columnas. Se han introducido las API siguientes para permitir el registro de proveedores personalizados de almacén de claves maestras en instancias de SqlConnection y SqlCommand:

public class SqlConnection
{
    public void RegisterColumnEncryptionKeyStoreProvidersOnConnection(IDictionary<string, SqlColumnEncryptionKeyStoreProvider> customProviders)
}
public class SqlCommand 
{
    public void RegisterColumnEncryptionKeyStoreProvidersOnCommand(IDictionary<string, SqlColumnEncryptionKeyStoreProvider> customProviders)
}

Se sigue admitiendo la API estática en SqlConnection (SqlConnection.RegisterColumnEncryptionKeyStoreProviders) para registrar globalmente proveedores personalizados de almacén de claves maestras. La caché de claves de cifrado de columnas mantenida globalmente solo se aplica a los proveedores registrados globalmente.

Precedencia del registro de proveedores de almacén de claves maestras de columna

Los proveedores integrados de almacén de claves maestras de columna que están disponibles para el almacén de certificados de Windows, el almacén de CNG y CSP están registrados previamente. No se debe registrar ningún proveedor en las instancias de conexión o de comando si se necesita uno de los proveedores integrados de almacén de claves maestras de columna.

Los proveedores personalizados de almacén de claves maestras se pueden registrar con el controlador en tres capas diferentes. El nivel global es el que se muestra actualmente. Los nuevos registros de nivel por conexión y por comando están vacíos inicialmente y se pueden establecer más de una vez.

Las precedencias de los tres registros son las siguientes:

  • El registro por comando se comprueba si no está vacío.
  • Si el registro por comando está vacío, el registro por conexión se comprueba si no está vacío.
  • Si el registro por conexión está vacío, se comprueba el registro global.

Una vez que se encuentre un proveedor de almacén de claves en el nivel de registro, el controlador NO vuelve a los demás registros para buscar un proveedor. Si los proveedores están registrados, pero no se encuentra el proveedor adecuado en un nivel, se produce una excepción que contiene únicamente los proveedores registrados en el registro comprobado.

Precedencia de la caché de claves de cifrado de columnas

El controlador no almacena en caché las claves de cifrado de columna (CEK) de los proveedores personalizados de almacén de claves registrados con las nuevas API de nivel de instancia. Los proveedores de almacén de claves deben implementar su propia memoria caché para aumentar el rendimiento. El controlador deshabilita esta caché local de claves de cifrado de columna implementadas por los proveedores personalizados de almacén de claves si la instancia del proveedor de almacén de claves está registrada en el controlador en el nivel global.

También se ha introducido una nueva API en la clase base SqlColumnEncryptionKeyStoreProvider para establecer el período de vida de la caché:

public abstract class SqlColumnEncryptionKeyStoreProvider
{
    // The default value of Column Encryption Key Cache Time to Live is 0.
    // Provider's local cache is disabled for globally registered providers.
    // Custom key store provider implementation must include column encryption key cache to provide caching support to locally registered providers.
    public virtual TimeSpan? ColumnEncryptionKeyCacheTtl { get; set; } = new TimeSpan(0);
}

Preferencia de dirección IP

Se ha introducido una nueva propiedad de conexión IPAddressPreference para indicar la preferencia de familia de direcciones IP al controlador al establecer conexiones TCP. Si Transparent Network IP Resolution (en .NET Framework) o Multi Subnet Failover se establecen en true, esta configuración no tiene ningún efecto. Existen tres valores aceptados para esta propiedad:

  • IPv4First

    • Este es el valor predeterminado. El controlador usa primero direcciones IPv4 resueltas. Si no es posible conectarse correctamente a ninguna de ellas, prueba con direcciones IPv6 resueltas.
  • IPv6First

    • El controlador usa primero direcciones IPv6 resueltas. Si no es posible conectarse correctamente a ninguna de ellas, prueba con direcciones IPv4 resueltas.
  • UsePlatformDefault

    • El controlador prueba las direcciones IP en el orden recibido en la respuesta de resolución DNS.

Compatibilidad con la plataforma de destino 3.0

  • .NET Framework 4.6.1+ (Windows x86, Windows x64)
  • .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)

Notas de la versión de Microsoft.Data.SqlClient 2.1

Las notas completas de la versión, incluidas las dependencias, están disponibles en el repositorio de GitHub: Notas de la versión 2.1.

Nuevas características de la versión 2.1

Compatibilidad entre plataformas para Always Encrypted

Microsoft.Data.SqlClient v2.1 amplía la compatibilidad con Always Encrypted en las siguientes plataformas:

Compatibilidad con Always Encrypted Compatibilidad de Always Encrypted con enclaves seguros Versión de .NET Framework de destino Microsoft.Data.SqlClient Version Sistema operativo
.NET Framework 4.6+ 1.1.0 Windows
.NET Core 2.1+ 2.1.0+1 Windows, Linux, macOS
Yes No2 .NET Standard 2.0 2.1.0+ Windows, Linux, macOS
.NET Standard 2.1+ 2.1.0+ Windows, Linux, macOS

Nota

1 Antes de la versión 2.1 de Microsoft.Data.SqlClient, Always Encrypted solo se admite en Windows. 2 Always Encrypted con enclaves seguros no se admite en .NET Standard 2.0.

Autenticación de flujo de código de los dispositivos de Microsoft Entra

Microsoft.Data.SqlClient v2.1 proporciona compatibilidad para la autenticación "flujo de código de dispositivo" con MSAL.NET. Documentación de referencia: Flujo de concesión de autorización de dispositivo de OAuth 2.0

Ejemplo de cadena de conexión:

Server=<server>.database.windows.net; Authentication=Active Directory Device Code Flow; Database=Northwind;Encrypt=True

La siguiente API permite personalizar el mecanismo de devolución de llamada del flujo de código del dispositivo:

public class ActiveDirectoryAuthenticationProvider
{
    // For .NET Framework, .NET Core and .NET Standard targeted applications
    public void SetDeviceCodeFlowCallback(Func<DeviceCodeResult, Task> deviceCodeFlowCallbackMethod)
}

Autenticación de identidad administrada de Microsoft Entra

Microsoft.Data.SqlClient v2.1 incluye compatibilidad con la autenticación de Microsoft Entra mediante identidades administradas.

Se admiten las siguientes palabras clave de modo de autenticación:

  • Identidad administrada de Active Directory
  • MSI de Active Directory (para la compatibilidad entre controladores de MS SQL)

Ejemplos de cadena de conexión:

// For System Assigned Managed Identity
"Server={serverURL}; Authentication=Active Directory MSI; Encrypt=True; Initial Catalog={db};"

// For System Assigned Managed Identity
"Server={serverURL}; Authentication=Active Directory Managed Identity; Initial Catalog={db};"

// For User Assigned Managed Identity
"Server={serverURL}; Authentication=Active Directory MSI; Encrypt=True; User Id={ObjectIdOfManagedIdentity}; Initial Catalog={db};"

// For User Assigned Managed Identity
"Server={serverURL}; Authentication=Active Directory Managed Identity; Encrypt=True; User Id={ObjectIdOfManagedIdentity}; Initial Catalog={db};"

Mejoras en la autenticación interactiva de Microsoft Entra

Microsoft.Data.SqlClient v2.1 agrega las siguientes API para personalizar la experiencia de autenticación de Microsoft Entra interactivo:

public class ActiveDirectoryAuthenticationProvider
{
    // For .NET Framework targeted applications only
    public void SetIWin32WindowFunc(Func<IWin32Window> iWin32WindowFunc);

    // For .NET Standard targeted applications only
    public void SetParentActivityOrWindowFunc(Func<object> parentActivityOrWindowFunc);

    // For .NET Framework, .NET Core and .NET Standard targeted applications
    public void SetAcquireAuthorizationCodeAsyncCallback(Func<Uri, Uri, CancellationToken, Task<Uri>> acquireAuthorizationCodeAsyncCallback);

    // For .NET Framework, .NET Core and .NET Standard targeted applications
    public void ClearUserTokenCache();
}

Sección de configuración SqlClientAuthenticationProviders

Microsoft.Data.SqlClient v2.1 presenta una nueva sección de configuración, SqlClientAuthenticationProviders (un clon de SqlAuthenticationProviders existente). La sección de configuración existente, SqlAuthenticationProviders, todavía se admite por compatibilidad con versiones anteriores cuando se define el tipo adecuado.

La nueva sección permite que los archivos de configuración de la aplicación contengan una sección SqlAuthenticationProviders para System.Data.SqlClient y una sección SqlClientAuthenticationProviders section para Microsoft.Data.SqlClient.

Autenticación de Microsoft Entra mediante un Id. de cliente de aplicación

Microsoft.Data.SqlClient v2.1 incluye compatibilidad para pasar un identificador de cliente de aplicación definido por el usuario a la Biblioteca de autenticación de Microsoft. El Id. de cliente de aplicación se usa al autenticarse con Microsoft Entra ID.

Se introdujeron las siguientes API nuevas:

  1. Se ha introducido un nuevo constructor en ActiveDirectoryAuthenticationProvider:
    [Se aplica a todas las plataformas de .NET (.NET Framework, .NET Core y .NET Standard)]

    public ActiveDirectoryAuthenticationProvider(string applicationClientId)
    

    Uso:

    string APP_CLIENT_ID = "<GUID>";
    SqlAuthenticationProvider customAuthProvider = new ActiveDirectoryAuthenticationProvider(APP_CLIENT_ID);
    SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, customAuthProvider);
    
    using (SqlConnection sqlConnection = new SqlConnection("<connection_string>")
    {
        sqlConnection.Open();
    }
    
  2. Se ha introducido una nueva propiedad de configuración en SqlAuthenticationProviderConfigurationSection y SqlClientAuthenticationProviderConfigurationSection:
    [Se aplica a .NET Framework and .NET Core]

    internal class SqlAuthenticationProviderConfigurationSection : ConfigurationSection
    {
        ...
        [ConfigurationProperty("applicationClientId", IsRequired = false)]
        public string ApplicationClientId => this["applicationClientId"] as string;
    }
    
    // Inheritance
    internal class SqlClientAuthenticationProviderConfigurationSection : SqlAuthenticationProviderConfigurationSection
    { ... }
    

    Uso:

    <configuration>
        <configSections>
            <section name="SqlClientAuthenticationProviders"
                             type="Microsoft.Data.SqlClient.SqlClientAuthenticationProviderConfigurationSection, Microsoft.Data.SqlClient" />
        </configSections>
        <SqlClientAuthenticationProviders applicationClientId ="<GUID>" />
    </configuration>
    
    <!--or-->
    
    <configuration>
        <configSections>
            <section name="SqlAuthenticationProviders"
                             type="Microsoft.Data.SqlClient.SqlAuthenticationProviderConfigurationSection, Microsoft.Data.SqlClient" />
        </configSections>
        <SqlAuthenticationProviders applicationClientId ="<GUID>" />
    </configuration>
    

Compatibilidad con la clasificación de datos v2

Microsoft.Data.SqlClient v2.1 incluye compatibilidad con la información de "rango de confidencialidad" de la clasificación de datos. Ahora están disponibles las siguientes API nuevas:

public class SensitivityClassification
{
    public SensitivityRank SensitivityRank;
}

public class SensitivityProperty
{
    public SensitivityRank SensitivityRank;
}

public enum SensitivityRank
{
    NOT_DEFINED = -1,
    NONE = 0,
    LOW = 10,
    MEDIUM = 20,
    HIGH = 30,
    CRITICAL = 40
}

Identificador de proceso de servidor para SqlConnection activo

Microsoft.Data.SqlClient v2.1 introduce una nueva propiedad SqlConnection, ServerProcessId, en una conexión activa.

public class SqlConnection
{
    // Returns the server process Id (SPID) of the active connection.
    public int ServerProcessId;
}

Compatibilidad del registro de seguimiento en SNI nativo

Microsoft.Data.SqlClient v2.1 amplía la implementación de SqlClientEventSource existente para habilitar el seguimiento de eventos en SNI.dll. Los eventos deben capturarse con una herramienta como Xperf.

El seguimiento se puede habilitar mediante el envío de un comando a SqlClientEventSource como se muestra a continuación:

// Enables trace events:
EventSource.SendCommand(eventSource, (EventCommand)8192, null);

// Enables flow events:
EventSource.SendCommand(eventSource, (EventCommand)16384, null);

// Enables both trace and flow events:
EventSource.SendCommand(eventSource, (EventCommand)(8192 | 16384), null);

Propiedad de la cadena de conexión "Tiempo de espera del comando"

Microsoft.Data.SqlClient v2.1 introduce la propiedad de la cadena de conexión "Tiempo de espera del comando" para reemplazar el valor predeterminado de 30 segundos. El tiempo de espera para los comandos individuales se puede invalidar mediante la propiedad CommandTimeout en SqlCommand.

Ejemplos de cadena de conexión:

"Server={serverURL}; Initial Catalog={db}; Encrypt=True; Integrated Security=true; Command Timeout=60"

Eliminación de símbolos de SNI nativo

Con Microsoft.Data.SqlClient v.2.1, hemos quitado los símbolos introducidos en v2.0.0 de NuGet Microsoft.Data.SqlClient.SNI.runtime a partir de la v2.1.1. Los símbolos públicos se publican ahora en el servidor de símbolos de Microsoft para herramientas como BinSkim que requieren acceso a símbolos públicos.

Vinculación de origen de símbolos de Microsoft.Data.SqlClient

A partir de Microsoft.Data.SqlClient v2.1, los símbolos de Microsoft.Data.SqlClient se vinculan por código fuente y se publican en el servidor de símbolos de Microsoft para una experiencia de depuración mejorada sin necesidad de descargar el código fuente.

Compatibilidad con la plataforma de destino 2.1

  • .NET Framework 4.6+ (Windows x86, Windows x64)
  • .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)

Notas de la versión de Microsoft.Data.SqlClient 2.0

Las notas completas de la versión, incluidas las dependencias, están disponibles en el repositorio de GitHub: Notas de la versión 2.0.

Cambios importantes en la versión 2.0

  • El modificador de acceso de la interfaz del proveedor de enclave SqlColumnEncryptionEnclaveProvider ha cambiado de public a internal.
  • Las constantes de la clase SqlClientMetaDataCollectionNames se han actualizado para reflejar los cambios en SQL Server.
  • El controlador realiza ahora la validación del certificado de servidor cuando el servidor SQL Server de destino aplica el cifrado TLS, que es el valor predeterminado para las conexiones de Azure.
  • SqlDataReader.GetSchemaTable() ahora devuelve un elemento DataTable vacío en lugar de null.
  • El controlador ahora realiza el redondeo de la escala decimal para que coincida con el comportamiento de SQL Server. Para obtener compatibilidad con versiones anteriores, el comportamiento anterior del truncamiento se puede habilitar mediante un modificador AppContext.
  • En el caso de las aplicaciones de .NET Framework que consumen Microsoft.Data.SqlClient, los archivos SNI.dll descargados previamente en las carpetas bin\x64 y bin\x86 ahora se denominan Microsoft.Data.SqlClient.SNI.x64.dll y Microsoft.Data.SqlClient.SNI.x86.dll, y se descargan en el directorio bin.
  • Por coherencia, los sinónimos nuevos de la propiedad cadena de conexión reemplazan a las propiedades anteriores cuando se recupera la cadena de conexión de SqlConnectionStringBuilder. Más información

Nuevas características de la versión 2.0

En Microsoft.Data.SqlClient 2.0 se han incorporado las características nuevas siguientes.

Resistencia ante errores de DNS

Ahora, el controlador copia en caché las direcciones IP de todas las conexiones correctas a un punto de conexión de SQL Server que admite la característica. Si se produce un error de resolución de DNS durante un intento de conexión, el controlador intenta establecer una conexión mediante una dirección IP copiada en caché para ese servidor, si existe.

Seguimiento de EventSource

Esta versión permite la captura de registros de seguimiento de eventos para la depuración de aplicaciones. Para capturar estos eventos, las aplicaciones cliente deben escuchar eventos de la implementación de EventSource de SqlClient:

Microsoft.Data.SqlClient.EventSource

Para obtener más información, vea cómo habilitar el seguimiento de eventos en SqlClient.

Habilitación de redes administradas en Windows

Un nuevo modificador de AppContext "Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows" permite el uso de una implementación de SNI administrada en Windows con fines de prueba y depuración. Este modificador alterna el comportamiento del controlador para usar un SNI administrado 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.

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

Vea Modificadores de AppContext en SqlClient para obtener una lista completa de los modificadores disponibles en el controlador.

Habilitación del comportamiento de truncamiento decimal

El controlador redondea la escala de datos decimal de forma predeterminada, tal y como lo hace SQL Server. Para obtener la compatibilidad con versiones anteriores, puede establecer el modificador de AppContext "Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal" en true.

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

Sinónimos nuevos de la propiedad de cadena de conexión

Se han agregado sinónimos nuevos para las siguientes propiedades de cadena de conexión existentes a fin de evitar la confusión de espaciado en torno a las propiedades con más de una palabra. Los nombres de propiedad antiguos siguen siendo compatibles con las versiones anteriores. Pero las nuevas propiedades de cadena de conexión ahora se incluyen al capturar la cadena de conexión de SqlConnectionStringBuilder.

Propiedad existente de cadena de conexión Nuevo sinónimo
Intención de aplicaciones Intención de aplicaciones
ConnectRetryCount Recuento de reintentos de conexión
ConnectRetryInterval Intervalo de reintentos de conexión
PoolBlockingPeriod Período de bloqueo del grupo
MultipleActiveResultSets Conjunto de resultados activo múltiple (MARS)
MultiSubnetFailover Conmutación por error de varias subredes
TransparentNetworkIPResolution Resolución de IP de red transparente
TrustServerCertificate TrustServerCertificate

Propiedad RowsCopied de SqlBulkCopy

La propiedad RowsCopied proporciona acceso de solo lectura al número de filas que se han procesado en la operación de copia masiva en curso. Este valor no necesariamente tiene que ser igual al número final de filas agregadas a la tabla de destino.

Invalidaciones de apertura de la conexión

El comportamiento predeterminado de SqlConnection.Open() se puede invalidar para deshabilitar el retraso de diez segundos y los reintentos de conexión automática que desencadenan los errores transitorios.

using SqlConnection sqlConnection = new SqlConnection("Data Source=(local);Integrated Security=true;Initial Catalog=AdventureWorks;");
sqlConnection.Open(SqlConnectionOverrides.OpenWithoutRetry);

Nota

Tenga en cuenta que esta invalidación solo se puede aplicar a SqlConnection.Open() y no a SqlConnection.OpenAsync().

Compatibilidad con el nombre de usuario para el modo interactivo de Active Directory

Se puede especificar un nombre de usuario en la cadena de conexión cuando se usa el modo interactivo de autenticación de Microsoft Entra para .NET Framework y .NET Core

Establezca un nombre de usuario mediante la propiedad de cadena de conexión User ID o UID:

"Server=<server name>; Database=<db name>; Authentication=Active Directory Interactive; User Id=<username>;Encrypt=True;"

Sugerencias de orden para SqlBulkCopy

Se pueden proporcionar sugerencias de orden para mejorar el rendimiento de las operaciones de copia masiva en tablas con índices agrupados. Para obtener más información, vea la sección Operaciones de copia masiva.

Cambios de dependencia de SNI

Microsoft.Data.SqlClient (.NET Core y .NET Standard) en Windows ahora depende de Microsoft.Data.SqlClient.SNI.runtime, reemplazando la dependencia anterior en runtime.native.System.Data.SqlClient.SNI. La dependencia nueva agrega compatibilidad con la plataforma ARM junto con las plataformas ya admitidas ARM64, x64 y x86 en Windows.

Compatibilidad con la plataforma de destino 2.0

  • .NET Framework 4.6+ (Windows x86, Windows x64)
  • .NET Core 2.1+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Windows ARM64, Windows ARM, Linux, macOS)

Notas de la versión de Microsoft.Data.SqlClient 1.1.0

Las notas completas de la versión, incluidas las dependencias, están disponibles en el repositorio de GitHub: Notas de la versión 1.1.

Nuevas características de la versión 1.1

Always Encrypted con enclaves seguros

Always Encrypted está disponible a partir de Microsoft SQL Server 2016. Los enclaves seguros están disponibles a partir de Microsoft SQL Server 2019. Para usar la característica de enclaves, las cadenas de conexión deben incluir el protocolo de atestación y la dirección URL de atestación necesarios. Por ejemplo:

"Attestation Protocol=HGS;Enclave Attestation Url=<attestation_url_for_HGS>"

Para más información, consulte:

Compatibilidad con la plataforma de destino 1.1

  • .NET Framework 4.6+ (Windows x86, Windows x64)
  • .NET Core 2.1+ (Windows x86, Windows x64, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Linux, macOS)

Notas de la versión de Microsoft.Data.SqlClient 1.0

La versión inicial del espacio de nombres Microsoft.Data.SqlClient ofrece más funcionalidades que el espacio de nombres System.Data.SqlClient existente.

Las notas completas de la versión, incluidas las dependencias, están disponibles en el repositorio de GitHub: Notas de la versión 1.0.

Nuevas características de la versión 1.0

Nuevas características de System.Data.SqlClient en .NET Framework 4.7.2

  • Clasificación de datos: disponible en Azure SQL Database y Microsoft SQL Server 2019.

  • Compatibilidad con UTF-8: disponible en Microsoft SQL Server 2019.

Nuevas características de System.Data.SqlClient en .NET Core 2.2

  • Clasificación de datos: disponible en Azure SQL Database y Microsoft SQL Server 2019.

  • Compatibilidad con UTF-8: disponible en Microsoft SQL Server 2019.

  • Autenticación: modo de autenticación de contraseña de Active Directory.

Clasificación de datos

La clasificación de datos proporciona un nuevo conjunto de API que exponen información de clasificación y confidencialidad de los datos de solo lectura de los objetos recuperados a través de SqlDataReader cuando el origen subyacente admite la característica y contiene metadatos de confidencialidad y clasificación de datos. Vea la aplicación de ejemplo en Detección y clasificación de datos en SqlClient.

public class SqlDataReader
{
    public Microsoft.Data.SqlClient.DataClassification.SensitivityClassification SensitivityClassification
}

namespace Microsoft.Data.SqlClient.DataClassification
{
    public class ColumnSensitivity
    {
        public System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Data.SqlClient.DataClassification.SensitivityProperty> SensitivityProperties
    }
    public class InformationType
    {
        public string Id
        public string Name
    }
    public class Label
    {
        public string Id
        public string Name
    }
    public class SensitivityClassification
    {
        public System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Data.SqlClient.DataClassification.ColumnSensitivity> ColumnSensitivities
        public System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Data.SqlClient.DataClassification.InformationType> InformationTypes
        public System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Data.SqlClient.DataClassification.Label> Labels
    }
    public class SensitivityProperty
    {
        public Microsoft.Data.SqlClient.DataClassification.InformationType InformationType
        public Microsoft.Data.SqlClient.DataClassification.Label Label
    }
}

Compatibilidad con UTF-8

La compatibilidad con UTF-8 no requiere hacer ningún cambio en el código de la aplicación. Estos cambios de SqlClient optimizan la comunicación entre el cliente y el servidor cuando el servidor admite UTF-8 y la intercalación de columna subyacente es UTF-8. Consulte la sección UTF-8 en Novedades de SQL Server 2019.

Always Encrypted con enclaves seguros

En general, la documentación existente que usa System.Data.SqlClient en .NET Framework y los proveedores de almacenamiento de claves maestras de columna integradas ahora deben trabajar también con .NET Core.

Desarrollar con Always Encrypted con el proveedor de datos .NET Framework

Always Encrypted: Protección de datos confidenciales y almacenamiento de claves de cifrado en el almacén de certificados de Windows

Authentication

Se pueden especificar diferentes modos de autenticación mediante la opción de cadena de conexión Autenticación. Para obtener más información, consulte la documentación de SqlAuthenticationMethod.

Nota

Los proveedores de almacén de claves personalizados, como el proveedor de Azure Key Vault, deberán actualizarse para admitir Microsoft.Data.SqlClient. Del mismo modo, también será necesario actualizar los proveedores de enclaves para que sean compatibles con Microsoft.Data.SqlClient. Always Encrypted solo se admite en los destinos de .NET Framework y .NET Core. No se admite con .NET Standard ya que en .NET Standard faltan algunas dependencias de cifrado.

Compatibilidad con la plataforma de destino 1.0

  • .NET Framework 4.6+ (Windows x86, Windows x64)
  • .NET Core 2.1+ (Windows x86, Windows x64, Linux, macOS)
  • .NET Standard 2.0+ (Windows x86, Windows x64, Linux, macOS)