Microsoft.Data.SqlClient 네임스페이스 소개

ADO.NET 다운로드

Microsoft.Data.SqlClient 네임스페이스는 기본적으로 System.Data.SqlClient 네임스페이스의 새 버전입니다. Microsoft.Data.SqlClient는 일반적으로 System.Data.SqlClient와 동일한 API 및 이전 버전과의 호환성을 유지합니다. 대부분의 애플리케이션에서 System.Data.SqlClient에서 Microsoft.Data.SqlClient로의 마이그레이션은 간단합니다. Microsoft.Data.SqlClient에 대한 NuGet 종속성을 추가하고 참조 및 using 문을 Microsoft.Data.SqlClient로 업데이트합니다.

System.Data.SqlClient에 비해 덜 사용되는 API에는 일부 애플리케이션에 영향을 줄 수 있는 몇 가지 차이점이 있습니다. 이러한 차이점에 대해서는 이 유용한 포팅 치트 시트를 참조하세요.

API 참조

Microsoft.Data.SqlClient API 세부 정보는 .NET API 브라우저에서 찾을 수 있습니다.

Microsoft.Data.SqlClient 5.2 릴리스 정보

5.2의 새로운 기능

  • .NET Standard에 대한 SqlDiagnosticListener 지원이 추가되었습니다. #1931
  • RowsCopied64에 새 속성 SqlBulkCopy가 추가되었습니다 . #2004자세히 보기
  • AccessTokenCallBack에 새 API SqlConnection이 추가되었습니다. #1260자세히 보기
  • Windows의 .NET에서 암호화를 위한 SuperSocketNetLib 레지스트리 옵션에 대한 지원이 추가되었습니다. #2047
  • .NET 6 이상에 대한 SqlBatch 지원이 추가되었습니다. #1825, #2223자세히 알아보기
  • 워크로드 ID 인증 지원이 추가되었습니다. #2159, #2264
  • .NET에 대한 지역화 지원이 추가되었습니다. #2210
  • 그루지야 문자 데이터 정렬에 대한 지원이 추가되었습니다. #2194
  • Big Endian 시스템에 대한 지원이 추가되었습니다. #2170
  • .NET 8 지원이 추가되었습니다. #2230
  • System.Runtime.Caching 8.0.0, System.Configuration.ConfigurationManager 8.0.0 및 System.Diagnostics.DiagnosticSource 8.0.0에서 주 .NET 버전 종속성에 대한 명시적 버전이 추가되었습니다. #2303
  • 별도의 패키지 파일에서 디버깅 기호를 생성하는 기능이 추가되었습니다. #2137

SqlBulkCopy에 새 속성 RowsCopied64 추가

SqlBulkCopy에 long 값 형식을 지원하는 새 속성 RowsCopied64가 있습니다.

기존 SqlBulkCopy.RowsCopied 동작은 변경되지 않습니다. 값이 int.MaxValue를 초과하면 RowsCopied가 음수를 반환할 수 있습니다.

예제 사용법:

    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;
            }
        }
    }

SqlConnection에 새 속성 AccessTokenCallBack 추가

SqlConnection은 페더레이션 인증 액세스 토큰을 반환하는 TokenCredential 대리인으로 새 AccessTokenCallBack 속성을 도입하여 Func<SqlAuthenticationParameters, CancellationToken,Task<SqlAuthenticationToken>> 인증을 지원합니다.

예제 사용법:

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

    const string defaultScopeSuffix = "/.default";
    string connectionString = GetConnectionString();
    using SqlConnection connection = new SqlConnection(connectionString);
    
    connection.AccessTokenCallback = async (authParams, cancellationToken) =>
    {
        var cred = new DefaultAzureCredential();
        string scope = authParams.Resource.EndsWith(defaultScopeSuffix) ? authParams.Resource : authParams.Resource + defaultScopeSuffix;
        AccessToken token = await cred.GetTokenAsync(new TokenRequestContext(new[] { scope }), cancellationToken);
        return new SqlAuthenticationToken(token.Token, token.ExpiresOn);
    }
    
    connection.Open();
    Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
    Console.WriteLine("State: {0}", connection.State);

SqlBatch API

예제 사용법:

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));
    }
}

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)

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리 5.2 릴리스 정보에서 제공됩니다.

5.1의 호환성이 손상되는 변경

  • .NET Core 3.1에 대한 지원이 중단되었습니다. #1704#1823

5.1의 새로운 기능

  • SqlParameter 값 및 GetFieldValue에 대한 DateOnlyTimeOnly 지원이 추가되었습니다. #1813
  • .NET Core 및 SNI 네이티브에 대한 TLS 1.3 지원이 추가되었습니다. #1821
  • Encrypt=Mandatory 또는 Encrypt=Strict에 대한 ServerCertificate 설정이 추가되었습니다. #1822자세히 보기
  • .NET Framework를 대상으로 할 때 Windows ARM64 지원이 추가되었습니다. #1828

서버 인증서

ServerCertificate 연결 설정의 기본값은 빈 문자열입니다. EncryptMandatory 또는 Strict로 설정된 경우 ServerCertificate는 서버의 TLS/SSL 인증서와 일치하는 인증서 파일에 대한 파일 시스템 경로를 지정하는 데 사용할 수 있습니다. 지정된 인증서가 유효하려면 정확히 일치해야 합니다. 허용되는 인증서 형식은 PEM, DER, CER입니다. 사용 예는 다음과 같습니다.

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

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)

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리 5.1 릴리스 정보에서 제공됩니다.

Microsoft.Data.SqlClient 5.0 릴리스 정보

5.0의 호환성이 손상되는 변경

  • .NET Framework 4.6.1 #1574에 대한 지원이 제거됨
  • Microsoft.SqlServer.Server 패키지에 대한 종속성이 추가되었습니다. 이 새로운 종속성은 애플리케이션이 해당 네임스페이스를 참조하고 .NET Core의 System.Data.SqlClient에 대한 패키지 참조(직접 또는 간접)가 여전히 있는 경우 네임스페이스 충돌을 일으킬 수 있습니다.
  • Microsoft.Data.SqlClient.Server 네임스페이스에서 클래스를 삭제하고 Microsoft.SqlServer.Server 패키지에서 지원되는 형식으로 대체했습니다.#1585. 영향을 받는 클래스 및 열거형은 다음과 같습니다.
    • 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

5.0의 새로운 기능

  • TDS8 지원이 추가되었습니다. TDS 8을 사용하려면 사용자가 연결 문자열에 Encrypt=Strict를 지정해야 합니다. #1608자세히 보기
  • 연결에서 서버 SPN 및 장애 조치(failover) 서버 SPN을 지정하기 위한 지원이 추가되었습니다. #1607자세히 보기
  • Windows에서 .NET Core를 대상으로 하는 경우 별칭에 대한 지원이 추가되었습니다. #1588자세히 보기
  • SqlDataSourceEnumerator가 추가되었습니다. #1430, 자세히 보기
  • 안전하지 않은 TLS 경고를 표시하지 않는 새 AppContext 스위치가 추가되었습니다. #1457, 자세히 보기

TDS 8 보안 강화

TDS 8을 사용하려면 연결 문자열에서 Encrypt=Strict를 지정합니다. Strict 모드는 TrustServerCertificate를 사용하지 않도록 설정합니다(항상 Strict 모드에서는 False로 처리됨). 일부 엄격한 모드 시나리오에 도움이 되도록 HostNameInCertificate가 추가되었습니다. TDS 8은 암호화된 안전한 TLS 연결 내에서 모든 서버 통신을 시작하고 계속합니다.

연결 암호화 동작을 명확히 하기 위해 새 암호화 값이 추가되었습니다. Encrypt=MandatoryEncrypt=True와 동일하며 TDS 연결 협상 중에 연결을 암호화합니다. Encrypt=OptionalEncrypt=False와 동일하며 서버가 TDS 연결 협상 중에 암호화가 필요하다고 클라이언트에 지시하는 경우에만 연결을 암호화합니다.

서버에 대한 연결 암호화에 대한 자세한 내용은 암호화 및 인증서 유효성 검사를 참조하세요.

HostNameInCertificate는 별칭을 사용하여 서버 식별을 위해 클라이언트에서 사용하는 이름과 다른 이름 또는 대체 주체 이름을 가진 서버 인증서가 있는 서버에 암호화를 사용하여 연결할 때 연결 문자열에 지정할 수 있습니다(예: DNS 별칭). 사용 예: HostNameInCertificate=MyDnsAliasName

서버 SPN

고유한 도메인/포리스트 토포그래피가 있는 환경에서 연결할 때 서버 SPN에 대한 특정 요구 사항이 있을 수 있습니다. ServerSPN/Server SPN 및 FailoverServerSPN/장애 조치 서버 SPN 연결 문자열 설정을 사용하여 도메인 환경에서 통합 인증 중에 사용되는 자동 생성된 서버 SPN을 재정의할 수 있습니다.

SQL 별칭 지원

사용자는 SQL Server 구성 관리자를 사용하여 별칭을 구성할 수 있습니다. 이러한 별칭은 Windows 레지스트리에 저장되며 .NET Framework를 대상으로 지정할 때 이미 지원됩니다. 이 릴리스에서는 Windows에서 .NET 또는 .NET Core를 대상으로 하는 경우 별칭을 지원합니다.

SQL 데이터 원본 열거자 지원

로컬 네트워크 내에서 사용 가능한 모든 SQL Server 인스턴스를 열거하는 메커니즘을 제공합니다.

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("============================");  
    }  
  }  

안전하지 않은 TLS 경고 표시 안 함

TLS 버전이 1.2 미만인 경우 서버와 협상하는 데 보안 경고가 콘솔에 출력됩니다. 애플리케이션 시작 시 다음 AppContext 스위치를 사용하도록 설정하면 Encrypt = false 동안 SQL 연결에서 이 경고가 표시되지 않을 수 있습니다.

Switch.Microsoft.Data.SqlClient.SuppressInsecureTLSWarning

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)

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리: 5.0 릴리스 정보에서 제공됩니다.

Microsoft.Data.SqlClient 4.1 릴리스 정보

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리: 4.1 릴리스 정보에서 제공됩니다.

4.1의 새로운 기능

증명 프로토콜 None 소개

새 증명 프로토콜 None이 연결 문자열에서 허용됩니다. 이 프로토콜을 사용하면 사용자가 VBS enclave에 대한 enclave 증명을 사용하지 않을 수 있습니다. 이 프로토콜이 설정되면 enclave 증명 URL 속성은 선택 사항이 됩니다.

연결 문자열 예:

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

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)

Microsoft.Data.SqlClient 4.0 릴리스 정보

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리: 4.0 릴리스 정보에서 제공됩니다.

4.0의 호환성이 손상되는 변경

  • Encrypt 연결 문자열 속성이 기본적으로 true가 되도록 변경되었습니다. #1210자세한 정보
  • 이제 드라이버는 Active Directory 인증 모드의 AggregateException을 대체하는 SqlException을 throw합니다. #1213
  • .NET Framework에서 사용되지 않는 Asynchronous Processing 연결 속성을 삭제했습니다. #1148
  • Configurable Retry Logic 안전 스위치를 제거했습니다. #1254자세한 정보
  • .NET Core 2.1에 대한 지원이 중단되었습니다. #1272
  • [.NET Framework] Active Directory Integrated 인증을 사용할 때 연결 문자열에 사용자 ID가 제공되면 예외가 throw되지 않습니다. #1359

4.0의 새로운 기능

true로 설정된 기본값 암호화

Encrypt 연결 설정의 기본값이 false에서 true로 변경되었습니다. 클라우드 데이터베이스의 사용이 증가하고 이러한 연결이 안전한지 확인해야 할 필요성이 증가함에 따라, 이전 버전과의 호환성이 손상되는 변경이 필요합니다.

암호화가 필요할 때 연결이 실패하는지 확인

클라이언트 암호화 라이브러리를 사용하지 않도록 설정하거나 사용할 수 없는 시나리오에서 암호화가 true로 설정되었거나 서버에 암호화가 필요할 때 암호화되지 않은 연결이 가능했습니다.

시스템 기본 프로토콜을 사용하기 위한 앱 컨텍스트 전환

TLS 1.3은 드라이버에서 지원되지 않습니다. 따라서 기본적으로 지원되는 프로토콜 목록에서 제거되었습니다. 사용자는 다음 앱 컨텍스트 전환을 사용하도록 설정하여 운영 체제의 클라이언트 프로토콜 강제 사용으로 다시 전환할 수 있습니다.

Switch.Microsoft.Data.SqlClient.UseSystemDefaultSecureProtocols

최적화된 매개 변수 바인딩 사용

Microsoft.Data.SqlClient는 많은 수의 매개 변수가 있는 쿼리의 성능을 향상시키기 위해 새로운 SqlCommand API, EnableOptimizedParameterBinding을 도입했습니다. 이 속성은 기본적으로 사용되지 않습니다. true로 설정하면 명령이 실행될 때 매개 변수 이름이 SQL Server 인스턴스로 전송되지 않습니다.

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

구성 가능한 다시 시도 논리 안전 전환 제거

구성 가능한 다시 시도 논리 기능을 사용하기 위해 앱 컨텍스트 스위치 "Switch.Microsoft.Data.SqlClient.EnableRetryLogic"이 더 이상 필요하지 않습니다. 이 기능은 이제 프로덕션에서 지원됩니다. 이 기능의 기본 동작은 계속해서 비재시도 정책으로 유지되며 다시 시도를 사용하도록 설정하려면 클라이언트 애플리케이션이 재정의해야 합니다.

SqlLocalDb 공유 인스턴스 지원

이제 관리 SNI를 사용할 때 SqlLocalDb 공유 인스턴스가 지원됩니다.

  • 가능한 시나리오:
    • (localdb)\.(SqlLocalDb의 기본 인스턴스에 연결)
    • (localdb)\<named instance>
    • (localdb)\.\<shared instance name>(*새로 추가된 지원)

GetFieldValueAsync<T>GetFieldValue<T>에서 XmlReader, TextReaderStream 형식 지원

GetFieldValueAsync<T>GetFieldValue<T>를 사용할 때 이제 XmlReader, TextReaderStream 형식이 지원됩니다.

예제 사용법:

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
                }
            }
        }
    }
}

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)

Microsoft.Data.SqlClient 3.0 릴리스 정보

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리: 3.0 릴리스 정보에서 제공됩니다.

3.0의 호환성이 손상되는 변경

  • 지원되는 최소 .NET Framework 버전이 v4.6.1로 증가했습니다. .NET Framework v4.6.0은 더 이상 지원되지 않습니다. #899
  • User Id 연결 속성에는 이제 사용자가 할당한 관리 ID에 대해 Object Id 대신 Client Id가 필요합니다. #1010자세한 정보
  • SqlDataReader는 이제 빈 byte[] 값 대신 DBNull 값을 반환합니다. 레거시 동작은 AppContext 스위치 Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior를 설정하여 사용하도록 설정할 수 있습니다. #998자세한 정보

3.0의 새로운 기능

구성 가능한 다시 시도 논리

이 새로운 기능은 클라이언트 애플리케이션이 “일시적” 또는 “다시 시도 가능” 오류를 다시 시도하도록 구성 가능한 지원을 도입합니다. 코드 또는 앱 구성 파일을 통해 구성을 수행할 수 있으며 연결을 열거나 명령을 실행하는 데 다시 시도 작업을 적용할 수 있습니다. 이 기능은 기본적으로 사용되지 않으며 현재 미리 보기 상태입니다. 이 지원을 사용하려면 클라이언트 애플리케이션에서 다음 안전 스위치를 켜야 합니다.

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

.NET AppContext 스위치를 사용하도록 설정되면 개별적으로 또는 다양한 사용자 지정 옵션을 사용하여 함께 SqlConnectionSqlCommand에 대한 다시 시도 논리 정책을 정의할 수 있습니다.

사용자 지정 SqlRetryLogicBaseProvider 구현을 등록하기 위해 SqlConnectionSqlCommand에 새 공개 API가 도입되었습니다.

public SqlConnection
{
    public SqlRetryLogicBaseProvider RetryLogicProvider;
}

public SqlCommand
{
    public SqlRetryLogicBaseProvider RetryLogicProvider;
}

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)
};

기존 코드를 수정하지 않고도 구성 파일에서 동일한 등록을 수행할 수 있는 새로운 구성 섹션도 도입되었습니다.

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

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

구성 파일에서 새로운 구성 섹션을 사용하는 간단한 예는 다음과 같습니다.

<?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>

또는 애플리케이션은 SqlRetryLogicBaseProvider 기본 클래스의 자체 공급자를 구현하고 SqlConnection/SqlCommand에 등록할 수 있습니다.

이벤트 카운터

이제 .NET Core 3.1 이상 및 .NET Standard 2.1 이상을 대상으로 하는 애플리케이션에 다음 카운터를 사용할 수 있습니다.

속성 표시 이름 설명
active-hard-connections 현재 서버에 대해 설정된 실제 활성 연결 데이터베이스 서버에 현재 열린 연결 수입니다.
hard-connects 서버에 대한 실제 연결 비율 데이터베이스 서버에 대해 열려 있는 초당 연결 수입니다.
hard-disconnects 서버의 실제 연결 끊김 속도 데이터베이스 서버에 대해 이루어지는 초당 연결 끊김 수입니다.
active-soft-connects 연결 풀에서 검색된 실제 연결 연결 풀에서 사용 중인 이미 열린 연결 수입니다.
soft-connects 연결 풀에서 검색된 연결 비율 연결 풀에서 사용 중인 초당 연결 수입니다.
soft-disconnects 연결 풀으로 반환된 연결 비율 연결 풀로 반환되는 초당 연결 수입니다.
number-of-non-pooled-connections 연결 풀링을 사용하지 않는 연결 수 풀링되지 않은 활성 연결 수입니다.
number-of-pooled-connections 연결 풀에서 관리하는 연결 수 연결 풀링 인프라를 관리하는 활성 연결 수입니다.
number-of-active-connection-pool-groups 활성 고유 연결 문자열 수 활성화되어 있는 고유 연결 풀 그룹 수입니다. 이 카운터는 AppDomain에서 찾은 고유 연결 문자열 수를 기준으로 합니다.
number-of-inactive-connection-pool-groups 정리 대기 중인 고유 연결 문자열 수 정리로 표시된 고유 연결 풀 그룹 수입니다. 이 카운터는 AppDomain에서 찾은 고유 연결 문자열 수를 기준으로 합니다.
number-of-active-connection-pools 활성 연결 풀 수 연결 풀의 총 수입니다.
number-of-inactive-connection-pools 비활성 연결 풀 수 최근 활동이 없으며 삭제 대기 중인 비활성 연결 풀 수입니다.
number-of-active-connections 활성 연결 수 현재 사용 중인 활성 연결 수입니다.
number-of-free-connections 연결 풀의 준비된 연결 수 연결 풀에서 사용할 수 있는 열린 연결 수입니다.
number-of-stasis-connections 현재 준비 대기 중인 연결 수 현재 작업 완료 대기 중이므로 사용자가 애플리케이션에서 사용할 수 없는 연결 수입니다.
number-of-reclaimed-connections GC에서 회수된 연결 수 애플리케이션에서 Close 또는 Dispose를 호출하지 않은 경우 가비지 수집을 통해 회수된 연결 수입니다. 참고 명시적으로 연결을 닫거나 삭제하지 않으면 성능이 저하됩니다.

이 카운터는 Windows 또는 Linux와 Windows의 PerfView에서 공급자 이름으로 Microsoft.Data.SqlClient.EventSource를 사용하여 .NET Core 전역 CLI 도구인 dotnet-tracedotnet-counters와 함께 사용할 수 있습니다. 자세한 내용은 이벤트 카운터 값 검색을 참조하세요.

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

Azure ID 종속성 소개

Microsoft.Data.SqlClient는 이제 "Active Directory 관리 ID/MSI" 및 "Active Directory 서비스 주체" 인증 모드에 대한 토큰을 획득하기 위해 Azure.Identity 라이브러리에 의존합니다. 이 변경으로 인해 공개 노출 영역이 다음과 같이 변경됩니다.

  • 호환성이 손상되는 변경
    이제 "사용자 ID" 연결 속성에는 "사용자가 할당한 관리 ID"에 대한 "개체 ID" 대신 "클라이언트 ID"가 필요합니다.
  • 퍼블릭 API
    새 읽기 전용 퍼블릭 속성: SqlAuthenticationParameters.ConnectionTimeout
  • 종속성
    Azure.Identity v1.3.0

SNI.dll의 이벤트 추적 개선 사항

Microsoft.Data.SqlClient.SNI(.NET Framework 종속성) 및 Microsoft.Data.SqlClient.SNI.runtime(.NET Core/Standard 종속성) 버전이 v3.0.0-preview1.21104.2로 업데이트되었습니다. SNI.dll의 이벤트 추적은 더 이상 클라이언트 애플리케이션을 통해 사용하도록 설정되지 않습니다. xperf 또는 perfview와 같은 도구를 통해 Microsoft.Data.SqlClient.EventSource 공급자에 대한 세션을 구독하는 것으로 충분합니다. 자세한 내용은 네이티브 SNI의 이벤트 추적 지원을 참조하세요.

행 버전 null 동작 사용

SqlDataReader는 빈 byte[] 값 대신 DBNull 값을 반환합니다. 레거시 동작을 사용하도록 설정하려면 애플리케이션 시작 시 "Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior" AppContext 스위치를 사용하도록 설정해야 합니다.

Microsoft Entra 기본 인증 지원

참고 항목

Microsoft Entra ID는 Azure AD(Azure Active Directory)의 새 이름이지만 기존 환경의 중단을 방지하기 위해 UI 필드, 연결 공급자, 오류 코드 및 cmdlet과 같은 일부 하드 코딩된 요소에는 여전히 Azure AD가 남아 있습니다. 이 문서에서는 두 이름을 서로 바꾸어 쓸 수 있습니다.

이 PR에서는 새로운 SQL 인증 방법인 Active Directory Default가 도입되었습니다. 이 인증 모드는 Microsoft Entra ID로 사용자 인증의 가능성을 확대하여 로그인 솔루션을 클라이언트 환경, Visual Studio Code, Visual Studio, Azure CLI 등으로 확장합니다.

이 인증 모드에서 드라이버는 액세스 토큰을 획득하기 위해 Azure ID 라이브러리에서 “DefaultAzureCredential”을 전달하여 토큰을 획득합니다. 이 모드는 다음 순서로 액세스 토큰을 획득하기 위해 이러한 자격 증명 형식을 사용하려고 시도합니다.

  • EnvironmentCredential
    • 클라이언트와 비밀 또는 사용자 이름과 암호, AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_CLIENT_CERTIFICATE_PATH, AZURE_USERNAME, AZURE_PASSWORD 환경 변수에 구성된 세부 정보를 사용하여 Microsoft Entra ID로 인증을 사용하도록 설정합니다(자세한 정보).
  • ManagedIdentityCredential
    • 배포 환경에 할당된 관리 ID를 사용하여 Microsoft Entra ID로 인증을 시도합니다. “사용자가 할당한 관리 ID”의 “클라이언트 ID”“사용자 ID” 연결 속성에서 읽습니다.
  • SharedTokenCacheCredential
    • Microsoft 애플리케이션 간에 공유되는 로컬 캐시에서 토큰을 사용하여 인증합니다.
  • VisualStudioCredential
    • Visual Studio의 데이터를 사용하여 Microsoft Entra ID로 인증을 사용하도록 설정합니다.
  • VisualStudioCodeCredential
    • Visual Studio Code의 데이터를 사용하여 Microsoft Entra ID로 인증을 사용하도록 설정합니다.
  • AzureCliCredential
    • 액세스 토큰을 가져오기 위해 Azure CLI를 사용하여 Microsoft Entra ID로 인증을 사용하도록 설정합니다.

"Active Directory Default"의 드라이버 구현에서 InteractiveBrowserCredential은 사용되지 않으며 MFA/대화형 인증을 사용하여 토큰을 획득하는 데 사용할 수 있는 유일한 옵션은 "Active Directory Interactive"입니다.*

현재 추가 사용자 지정 옵션은 사용할 수 없습니다.

사용자 지정 마스터 키 저장소 공급자 등록 향상

이제 Microsoft.Data.SqlClient는 다중 테넌트 애플리케이션 및 해당 열 암호화/암호 해독 사용을 더 효과적으로 지원하기 위해 애플리케이션에서 마스터 키 저장소 공급자가 액세스할 수 있는 위치를 더 세밀하게 제어합니다. 다음 API는 인스턴스 SqlConnectionSqlCommand 인스턴스에서 사용자 지정 마스터 키 저장소 공급자를 등록할 수 있도록 도입되었습니다.

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

사용자 지정 마스터 키 저장소 공급자를 등록하기 위한 SqlConnection의 정적 API(SqlConnection.RegisterColumnEncryptionKeyStoreProviders)가 계속 지원됩니다. 전역적으로 유지 관리되는 열 암호화 키 캐시는 전역적으로 등록된 공급자에만 적용됩니다.

열 마스터 키 저장소 공급자 등록 우선 순위

Windows 인증서 저장소, CNG 저장소, CSP에 사용할 수 있는 기본 제공 열 마스터 키 저장소 공급자는 미리 등록됩니다. 기본 제공 열 마스터 키 저장소 공급자 중 하나가 필요한 경우 연결 또는 명령 인스턴스에 공급자를 등록해서는 안 됩니다.

사용자 지정 마스터 키 저장소 공급자는 세 가지 계층에서 드라이버에 등록할 수 있습니다. 전역 수준은 현재와 같습니다. 새로운 연결별 및 명령별 수준 등록은 처음에는 비어 있으며 두 번 이상 설정할 수 있습니다.

세 가지 등록의 우선 순위는 다음과 같습니다.

  • 명령별 등록이 비어 있지 않은지 확인됩니다.
  • 명령별 등록이 비어 있는 경우 연결별 등록이 비어 있지 않은지 확인됩니다.
  • 연결별 등록이 비어 있는 경우 전역 등록이 확인됩니다.

등록 수준에서 키 저장소 공급자가 발견되면 드라이버는 공급자를 검색하기 위해 다른 등록으로 대체되지 않습니다. 공급자가 등록되었지만 적절한 공급자가 특정 수준에 없는 경우 확인된 등록에서 등록된 공급자만 포함하는 예외가 throw됩니다.

열 암호화 키 캐시 우선 순위

드라이버는 새 인스턴스 수준 API를 사용하여 등록된 사용자 지정 키 저장소 공급자의 CEK(열 암호화 키)를 캐시하지 않습니다. 키 저장소 공급자는 성능을 향상하기 위해 자체 캐시를 구현해야 합니다. 드라이버는 키 저장소 공급자 인스턴스가 전역 수준에서 드라이버에 등록된 경우 사용자 지정 키 저장소 공급자가 구현한 열 암호화 키의 로컬 캐시를 사용하지 않도록 설정합니다.

캐시 시간을 라이브로 설정하기 위해 SqlColumnEncryptionKeyStoreProvider 기본 클래스에 대한 새 API도 도입되었습니다.

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);
}

IP 주소 기본 설정

TCP 연결을 설정할 때 드라이버에 대한 IP 주소 패밀리 기본 설정을 지정하기 위해 새로운 연결 속성 IPAddressPreference가 도입되었습니다. Transparent Network IP Resolution(.NET Framework) 또는 Multi Subnet Failovertrue로 설정된 경우 이 설정은 적용되지 않습니다. 이 속성에 허용되는 세 가지 값은 다음과 같습니다.

  • IPv4First

    • 이 값은 기본값입니다. 드라이버는 먼저 확인된 IPv4 주소를 사용합니다. 성공적으로 연결할 수 없는 경우 확인된 IPv6 주소를 시도합니다.
  • IPv6First

    • 드라이버는 먼저 확인된 IPv6 주소를 사용합니다. 성공적으로 연결할 수 없는 경우 확인된 IPv4 주소를 시도합니다.
  • UsePlatformDefault

    • 드라이버는 DNS 확인 응답에서 받은 순서대로 IP 주소를 시도합니다.

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)

Microsoft.Data.SqlClient 2.1 릴리스 정보

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리: 2.1 릴리스 정보에서 제공됩니다.

2.1의 새로운 기능

Always Encrypted에 대한 플랫폼 간 지원

Microsoft.Data.SqlClient v2.1은 다음 플랫폼에서 Always Encrypted에 대한 지원을 확장합니다.

Always Encrypted 지원 보안 Enclave로 Always Encrypted 지원 대상 프레임워크 Microsoft.Data.SqlClient 버전 운영 체제
.NET Framework 4.6+ 1.1.0+ Windows
.NET Core 2.1 이상 2.1.0+1 Windows, Linux, macOS
아니요2 .NET Standard 2.0 2.1.0+ Windows, Linux, macOS
.NET Standard 2.1+ 2.1.0+ Windows, Linux, macOS

참고 항목

1 Microsoft.Data.SqlClient 버전 v2.1 이전에서 Always Encrypted는 Windows에서만 지원됩니다. 2 보안 Enclave를 사용한 Always Encrypted는 .NET Standard 2.0에서 지원되지 않습니다.

Microsoft Entra 디바이스 코드 흐름 인증

Microsoft.Data.SqlClient v2.1은 MSAL.NET을 사용하여 "디바이스 코드 흐름" 인증을 지원합니다. 참조 설명서: OAuth2.0 디바이스 인증 권한 부여 흐름

연결 문자열 예:

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

다음 API를 사용하면 디바이스 코드 흐름 콜백 메커니즘을 사용자 지정할 수 있습니다.

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

Microsoft Entra 관리 ID 인증

Microsoft.Data.SqlClient v2.1에서는 관리 ID를 사용하는 Microsoft Entra 인증을 지원합니다.

다음 인증 모드 키워드가 지원됩니다.

  • Active Directory 관리 ID
  • Active Directory MSI(MS SQL 드라이버 간 호환성용)

연결 문자열 예제:

// 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};"

Microsoft Entra 대화형 인증 향상

Microsoft.Data.SqlClient v2.1은 다음 API를 추가하여 Microsoft Entra 대화형 인증 환경을 사용자 지정합니다.

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();
}

SqlClientAuthenticationProviders 구성 섹션

Microsoft.Data.SqlClient v2.1에서는 새로운 구성 섹션 SqlClientAuthenticationProviders(기존 SqlAuthenticationProviders의 복제)를 지원합니다. 기존 구성 섹션(SqlAuthenticationProviders)은 적절한 유형이 정의된 경우 이전 버전과의 호환성을 위해 계속 지원됩니다.

새로운 섹션에서는 애플리케이션 구성 파일에 System.Data.SqlClient의 SqlAuthenticationProviders 섹션과 Microsoft.Data.SqlClient의 SqlClientAuthenticationProviders 섹션을 모두 포함할 수 있습니다.

애플리케이션 클라이언트 ID를 사용한 Microsoft Entra 인증

Microsoft.Data.SqlClient v2.1에서는 사용자 정의 애플리케이션 클라이언트 ID를 Microsoft 인증 라이브러리에 전달하는 기능을 지원합니다. 애플리케이션 클라이언트 ID는 Microsoft Entra ID로 인증할 때 사용됩니다.

다음 새 API가 도입되었습니다.

  1. ActiveDirectoryAuthenticationProvider에 새 생성자가 도입되었습니다.
    [적용 대상: 모든 .NET 플랫폼(.NET Framework, .NET Core 및 .NET Standard)]

    public ActiveDirectoryAuthenticationProvider(string applicationClientId)
    

    사용법:

    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. SqlAuthenticationProviderConfigurationSectionSqlClientAuthenticationProviderConfigurationSection에 새 구성 속성이 도입되었습니다.
    [적용 대상: NET Framework 및 .NET Core]

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

    사용법:

    <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>
    

데이터 분류 v2 지원

Microsoft.Data.SqlClient v2.1에서는 데이터 분류의 "민감도 순위" 정보를 지원합니다. 이제 다음과 같은 새 API를 사용할 수 있습니다.

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
}

활성 SqlConnection의 서버 프로세스 ID

Microsoft.Data.SqlClient v2.1에서는 활성 연결에 새 SqlConnection 속성 ServerProcessId가 도입되었습니다.

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

네이티브 SNI에서 추적 로깅 지원

Microsoft.Data.SqlClient v2.1에서는 기존 SqlClientEventSource 구현을 확장하여 SNI.dll에서 이벤트 추적을 사용하도록 설정합니다. Xperf와 같은 도구를 사용하여 이벤트를 캡처해야 합니다.

다음과 같이 SqlClientEventSource에 명령을 보내 추적을 사용하도록 설정할 수 있습니다.

// 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);

"명령 시간 제한 " 연결 문자열 속성

Microsoft.Data.SqlClient v2.1에서는 기본값인 30초를 재정의하는 "명령 시간 제한" 연결 문자열 속성이 도입되었습니다. SqlCommand의 CommandTimeout 속성을 사용하여 개별 명령의 시간 제한을 재정의할 수 있습니다.

연결 문자열 예제:

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

네이티브 SNI에서 기호 제거

Microsoft.Data.SqlClient v2.1에서는 v2.0.0에 도입된 기호를 v2.1.1부터 Microsoft.Data.SqlClient.SNI.runtime NuGet에서 제거했습니다. 이제 공용 기호에 액세스해야 하는 BinSkim과 같은 도구를 위해 Microsoft 기호 서버에 공용 기호가 게시됩니다.

Microsoft.Data.SqlClient 기호의 소스 연결

Microsoft.Data.SqlClient v2.1부터 Microsoft.Data.SqlClient 기호는 소스와 연결되어 있으며 소스 코드를 다운로드할 필요 없이 향상된 디버깅 환경을 위해 Microsoft 기호 서버에 게시됩니다.

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)

Microsoft.Data.SqlClient 2.0 릴리스 정보

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리: 2.0 릴리스 정보에서 제공됩니다.

2.0의 주요 변경 내용

  • enclave 공급자 인터페이스 SqlColumnEncryptionEnclaveProvider에 대한 액세스 한정자가 public에서 internal로 변경되었습니다.
  • SqlClientMetaDataCollectionNames 클래스의 상수가 SQL Server 변경 내용을 반영하도록 업데이트되었습니다.
  • 이제 드라이버는 대상 SQL Server에서 TLS 암호화를 적용할 때 서버 인증서 유효성 검사를 수행하며, 이 동작은 Azure 연결을 위한 기본값입니다.
  • SqlDataReader.GetSchemaTable()은 이제 null 대신 빈 DataTable을 반환합니다.
  • 이제 드라이버는 SQL Server 동작과 일치하도록 소수 자릿수 반올림을 수행합니다. 이전 버전과의 호환성을 위해 AppContext 스위치를 사용하여 이전 잘라내기 동작을 사용하도록 설정할 수 있습니다.
  • Microsoft.Data.SqlClient를 사용하는 .NET Framework 애플리케이션의 경우 이전에 bin\x64bin\x86 폴더에 다운로드되던 SNI.dll 파일이 bin 디렉터리에 다운로드되며 파일 이름이 Microsoft.Data.SqlClient.SNI.x64.dllMicrosoft.Data.SqlClient.SNI.x86.dll로 지정됩니다.
  • 일관성을 위해 SqlConnectionStringBuilder에서 연결 문자열을 가져올 때 새 연결 문자열 속성 동의어가 이전 속성을 대체합니다. 자세히 알아보기

2.0의 새로운 기능

Microsoft.Data.SqlClient 2.0에는 다음과 같은 새로운 기능이 도입되었습니다.

DNS 오류 복원력

이제 드라이버는 기능을 지원하는 SQL Server 엔드포인트에 대한 모든 성공적인 연결의 IP 주소를 캐시합니다. 연결 시도 중에 DNS 확인 오류가 발생하면 드라이버는 해당 서버의 캐시된 IP 주소(있는 경우)를 사용하여 연결을 설정하려고 시도합니다.

EventSource 추적

이 릴리스에서는 애플리케이션 디버깅을 위한 이벤트 추적 로그 캡처를 지원합니다. 이러한 이벤트를 캡처하려면 클라이언트 애플리케이션이 SqlClient의 EventSource 구현에서 이벤트를 수신 대기해야 합니다.

Microsoft.Data.SqlClient.EventSource

자세한 내용은 SqlClient에서 이벤트 추적을 사용하는 방법을 확인합니다.

Windows에서 관리 네트워킹 사용

새로운 AppContext 스위치 “Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows”를 사용하면 테스트 및 디버깅을 위해 Windows에서 관리형 SNI 구현을 사용할 수 있습니다. 이 스위치는 Windows의 .NET Core 2.1 이상 및 .NET Standard 2.0 이상 프로젝트에서 관리 SNI를 사용하도록 드라이버의 동작을 토글하여 Microsoft.Data.SqlClient 라이브러리의 네이티브 라이브러리에 대한 모든 종속성을 제거합니다.

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

드라이버에서 사용 가능한 스위치의 전체 목록은 SqlClient의 AppContext 스위치를 참조하세요.

소수점 잘라내기 동작 사용

드라이버는 decimal 데이터 소수 자릿수를 SQL Server에서 반올림되는 것처럼 기본적으로 반올림합니다. 이전 버전과의 호환성을 위해 AppContext 스위치 "Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal"true로 설정할 수 있습니다.

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

새 연결 문자열 속성 동의어

두 단어 이상의 속성에 대한 간격 혼동을 방지하기 위해 다음과 같은 기존 연결 문자열 속성에 대한 새 동의어가 추가되었습니다. 이전 속성 이름은 이전 버전과의 호환성을 위해 계속 지원됩니다. 그러나 이제 SqlConnectionStringBuilder에서 연결 문자열을 가져올 때 새 연결 문자열 속성이 포함됩니다.

기존 연결 문자열 속성 새 동의어
ApplicationIntent Application Intent
ConnectRetryCount 연결 다시 시도 횟수
ConnectRetryInterval 연결 다시 시도 간격
PoolBlockingPeriod 풀 차단 기간
MultipleActiveResultSets MARS(Multiple Active Result Sets)
MultiSubnetFailover 여러 서브넷 장애 조치
TransparentNetworkIPResolution 투명 네트워크 IP 확인
TrustServerCertificate 서버 인증서 신뢰

SqlBulkCopy RowsCopied 속성

RowsCopied 속성은 진행 중인 대량 복사 작업에서 처리된 행의 수에 대한 읽기 전용 액세스를 제공합니다. 이 값이 대상 테이블에 추가된 최종 행 수와 반드시 같을 필요는 없습니다.

연결 열기 재정의

일시적인 오류로 인해 트리거되는 10초 지연 및 자동 연결 다시 시도를 사용하지 않도록 SqlConnection.Open()의 기본 동작을 재정의할 수 있습니다.

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

참고 항목

이 재정의는 SqlConnection.Open()에만 적용할 수 있으며 SqlConnection.OpenAsync()에는 적용되지 않습니다.

Active Directory 대화형 모드를 위한 사용자 이름 지원

.NET Framework 및 .NET Core 모두에 Microsoft Entra 대화형 인증 모드를 사용하는 경우 연결 문자열에 사용자 이름을 지정할 수 있습니다.

사용자 ID 또는 UID 연결 문자열 속성을 사용하여 사용자 이름을 설정합니다.

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

SqlBulkCopy의 정렬 힌트

클러스터형 인덱스가 있는 테이블에서 대량 복사 작업의 성능을 향상시키기 위해 정렬 힌트를 제공할 수 있습니다. 자세한 내용은 대량 복사 작업 섹션을 참조하세요.

SNI 종속성 변경 내용

Windows의 Microsoft.Data.SqlClient(.NET Core 및 .NET Standard)는 이제 Microsoft.Data.SqlClient.SNI.runtime에 종속되어 runtime.native.System.Data.SqlClient.SNI에 대한 이전 종속성을 대체합니다. 이 새 종속성은 기존에 지원되는 플랫폼인 Windows의 ARM64, x64, x86과 함께 ARM 플랫폼에 대한 지원을 추가합니다.

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)

Microsoft.Data.SqlClient 1.1.0 릴리스 정보

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리: 1.1 릴리스 정보에서 제공됩니다.

1.1의 새로운 기능

보안 enclave를 사용한 Always Encrypted

Always Encrypted는 Microsoft SQL Server 2016부터 사용할 수 있습니다. 보안 enclave는 Microsoft SQL Server 2019부터 사용할 수 있습니다. enclave 기능을 사용하려면 연결 문자열에 필수 증명 프로토콜 및 증명 URL이 포함되어야 합니다. 예시:

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

자세한 내용은 다음을 참조하세요.

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)

Microsoft.Data.SqlClient 1.0 릴리스 정보

Microsoft.Data.SqlClient 네임스페이스의 초기 릴리스는 기존 System.Data.SqlClient 네임스페이스에 비해 더 많은 기능을 제공합니다.

종속성을 포함한 전체 릴리스 정보는 GitHub 리포지토리: 1.0 릴리스 정보에서 제공됩니다.

1.0의 새로운 기능

.NET Framework 4.7.2 System.Data.SqlClient를 통한 새로운 기능

  • 데이터 분류 - Azure SQL 데이터베이스 및 Microsoft SQL Server 2019에서 사용할 수 있습니다.

  • UTF-8 지원 - Microsoft SQL Server 2019에서 사용할 수 있습니다.

NET Core 2.2 System.Data.SqlClient를 통한 새로운 기능

  • 데이터 분류 - Azure SQL 데이터베이스 및 Microsoft SQL Server 2019에서 사용할 수 있습니다.

  • UTF-8 지원 - Microsoft SQL Server 2019에서 사용할 수 있습니다.

  • 인증 - Active Directory 암호 인증 모드입니다.

데이터 분류

데이터 분류는 기본 원본이 기능을 지원하고 데이터 민감도 및 분류에 대한 메타데이터를 포함하는 경우 SqlDataReader를 통해 검색된 개체에 대한 읽기 전용 데이터 민감도 및 분류 정보를 노출하는 새로운 API 집합을 제공합니다. 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
    }
}

UTF-8 지원

UTF-8 지원은 애플리케이션 코드를 변경할 필요가 없습니다. 이러한 SqlClient 변경은 서버에서 UTF-8을 지원하고 기본 열 데이터 정렬이 UTF-8인 경우 클라이언트-서버 통신을 최적화합니다. SQL Server 2019의 새로운 기능에서 UTF-8 섹션을 참조하세요.

보안 enclave를 사용한 Always Encrypted

일반적으로 .NET Framework의 System.Data.SqlClient 및 기본 제공 열 마스터 키 저장소 공급자를 사용하는 기존 문서는 이제 .NET Core에서도 작동해야 합니다.

.NET Framework 데이터 공급자와 Always Encrypted를 사용하여 개발

Always Encrypted: 중요한 데이터 보호 및 Windows 인증서 저장소에 암호화 키 저장

인증

인증 연결 문자열 옵션을 사용하여 다양한 인증 모드를 지정할 수 있습니다. 자세한 내용은 SqlAuthenticationMethod 문서를 참조하세요.

참고 항목

Azure Key Vault 공급자와 같은 사용자 지정 키 저장소 공급자는 Microsoft.Data.SqlClient를 지원하도록 업데이트해야 합니다. 마찬가지로 Enclave 공급자도 Microsoft.Data.SqlClient를 지원하도록 업데이트해야 합니다. Always Encrypted는 .NET Framework 및 .NET Core 대상에 대해서만 지원됩니다. .NET Standard에는 특정 암호화 종속성이 없으므로 .NET Standard에 대해 지원되지 않습니다.

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)