From 46b1a3085af2e667c5caddf575c5b0e12c9554ba Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 2 Apr 2025 15:16:32 -0500 Subject: [PATCH 1/3] Split DbConnectionStringCommon classes into separate classes (will deal with utils in a bit) --- .../DbConnectionStringDefaults.cs | 64 ++++++ .../DbConnectionStringKeywords.cs | 72 ++++++ .../DbConnectionStringSynonyms.cs | 93 ++++++++ .../Data/Common/DbConnectionStringCommon.cs | 212 +----------------- 4 files changed, 232 insertions(+), 209 deletions(-) create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringDefaults.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringKeywords.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringSynonyms.cs diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringDefaults.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringDefaults.cs new file mode 100644 index 0000000000..de3971a1e4 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringDefaults.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Data.SqlClient; + +namespace Microsoft.Data.Common.ConnectionString +{ + internal static class DbConnectionStringDefaults + { + internal const ApplicationIntent ApplicationIntent = Microsoft.Data.SqlClient.ApplicationIntent.ReadWrite; + internal const string ApplicationName = + #if NETFRAMEWORK + "Framework Microsoft SqlClient Data Provider"; + #else + "Core Microsoft SqlClient Data Provider"; + #endif + internal const string AttachDBFilename = ""; + internal const SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified; + internal static readonly SqlAuthenticationMethod Authentication = SqlAuthenticationMethod.NotSpecified; + internal const SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled; + internal const int CommandTimeout = 30; + internal const int ConnectRetryCount = 1; + internal const int ConnectRetryInterval = 10; + internal const int ConnectTimeout = 15; + internal const bool ContextConnection = false; + internal const string CurrentLanguage = ""; + internal const string DataSource = ""; + internal const string EnclaveAttestationUrl = ""; + internal static readonly SqlConnectionEncryptOption Encrypt = SqlConnectionEncryptOption.Mandatory; + internal const bool Enlist = true; + internal const string FailoverPartner = ""; + internal const string FailoverPartnerSPN = ""; + internal const string HostNameInCertificate = ""; + internal const string InitialCatalog = ""; + internal const bool IntegratedSecurity = false; + internal const SqlConnectionIPAddressPreference IPAddressPreference = SqlConnectionIPAddressPreference.IPv4First; + internal const int LoadBalanceTimeout = 0; // default of 0 means don't use + internal const int MaxPoolSize = 100; + internal const int MinPoolSize = 0; + internal const bool MultipleActiveResultSets = false; + internal const bool MultiSubnetFailover = false; + internal const int PacketSize = 8000; + internal const string Password = ""; + internal const bool PersistSecurityInfo = false; + internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto; + internal const bool Pooling = true; + internal const bool Replication = false; + internal const string ServerCertificate = ""; + internal const string ServerSPN = ""; + internal const string TransactionBinding = "Implicit Unbind"; + internal const bool TrustServerCertificate = false; + internal const string TypeSystemVersion = "Latest"; + internal const string UserID = ""; + internal const bool UserInstance = false; + internal const string WorkstationID = ""; + + #if NETFRAMEWORK + internal const bool ConnectionReset = true; + internal static readonly bool TransparentNetworkIPResolution = !LocalAppContextSwitches.DisableTNIRByDefault; + internal const string NetworkLibrary = ""; + #endif + } +} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringKeywords.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringKeywords.cs new file mode 100644 index 0000000000..65cb781fa1 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringKeywords.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Data.Common.ConnectionString +{ + internal static class DbConnectionStringKeywords + { + // SqlClient + internal const string ApplicationIntent = "Application Intent"; + internal const string ApplicationName = "Application Name"; + internal const string AttachDBFilename = "AttachDbFilename"; + internal const string AttestationProtocol = "Attestation Protocol"; + internal const string Authentication = "Authentication"; + internal const string ColumnEncryptionSetting = "Column Encryption Setting"; + internal const string CommandTimeout = "Command Timeout"; + internal const string ConnectionReset = "Connection Reset"; + internal const string ConnectRetryCount = "Connect Retry Count"; + internal const string ConnectRetryInterval = "Connect Retry Interval"; + internal const string ConnectTimeout = "Connect Timeout"; + internal const string ContextConnection = "Context Connection"; + internal const string CurrentLanguage = "Current Language"; + internal const string DataSource = "Data Source"; + internal const string EnclaveAttestationUrl = "Enclave Attestation Url"; + internal const string Encrypt = "Encrypt"; + internal const string Enlist = "Enlist"; + internal const string FailoverPartner = "Failover Partner"; + internal const string FailoverPartnerSPN = "Failover Partner SPN"; + internal const string HostNameInCertificate = "Host Name In Certificate"; + internal const string InitialCatalog = "Initial Catalog"; + internal const string IntegratedSecurity = "Integrated Security"; + internal const string IPAddressPreference = "IP Address Preference"; + internal const string LoadBalanceTimeout = "Load Balance Timeout"; + internal const string MaxPoolSize = "Max Pool Size"; + internal const string MinPoolSize = "Min Pool Size"; + internal const string MultipleActiveResultSets = "Multiple Active Result Sets"; + internal const string MultiSubnetFailover = "Multi Subnet Failover"; + internal const string NetworkLibrary = "Network Library"; + internal const string PacketSize = "Packet Size"; + internal const string Password = "Password"; + internal const string PersistSecurityInfo = "Persist Security Info"; + internal const string PoolBlockingPeriod = "Pool Blocking Period"; + internal const string Pooling = "Pooling"; + internal const string Replication = "Replication"; + internal const string ServerCertificate = "Server Certificate"; + internal const string ServerSPN = "Server SPN"; + internal const string TransactionBinding = "Transaction Binding"; + internal const string TransparentNetworkIPResolution = "Transparent Network IP Resolution"; + internal const string TrustServerCertificate = "Trust Server Certificate"; + internal const string TypeSystemVersion = "Type System Version"; + internal const string UserID = "User ID"; + internal const string UserInstance = "User Instance"; + internal const string WorkstationID = "Workstation ID"; + + #if NETFRAMEWORK + // Odbc + internal const string Driver = "Driver"; + internal const string Dsn = "Dsn"; + internal const string FileDsn = "FileDsn"; + internal const string SaveFile = "SaveFile"; + + // OleDb + internal const string FileName = "File Name"; + internal const string OleDbServices = "OLE DB Services"; + internal const string Provider = "Provider"; + + // OracleClient + internal const string Unicode = "Unicode"; + internal const string OmitOracleConnectionName = "Omit Oracle Connection Name"; + #endif + } +} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringSynonyms.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringSynonyms.cs new file mode 100644 index 0000000000..f7d8881544 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringSynonyms.cs @@ -0,0 +1,93 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Data.Common.ConnectionString +{ + internal static class DbConnectionStringSynonyms + { + //internal const string TransparentNetworkIPResolution = TRANSPARENTNETWORKIPRESOLUTION; + internal const string TRANSPARENTNETWORKIPRESOLUTION = "transparentnetworkipresolution"; + + //internal const string ApplicationName = APP; + internal const string APP = "app"; + + // internal const string IPAddressPreference = IPADDRESSPREFERENCE; + internal const string IPADDRESSPREFERENCE = "ipaddresspreference"; + + //internal const string ApplicationIntent = APPLICATIONINTENT; + internal const string APPLICATIONINTENT = "applicationintent"; + + //internal const string AttachDBFilename = EXTENDEDPROPERTIES + "," + INITIALFILENAME; + internal const string EXTENDEDPROPERTIES = "extended properties"; + internal const string INITIALFILENAME = "initial file name"; + + // internal const string HostNameInCertificate = HOSTNAMEINCERTIFICATE; + internal const string HOSTNAMEINCERTIFICATE = "hostnameincertificate"; + + // internal const string ServerCertificate = SERVERCERTIFICATE; + internal const string SERVERCERTIFICATE = "servercertificate"; + + //internal const string ConnectTimeout = CONNECTIONTIMEOUT + "," +TIMEOUT; + internal const string CONNECTIONTIMEOUT = "connection timeout"; + internal const string TIMEOUT = "timeout"; + + //internal const string ConnectRetryCount = CONNECTRETRYCOUNT; + internal const string CONNECTRETRYCOUNT = "connectretrycount"; + + //internal const string ConnectRetryInterval = CONNECTRETRYINTERVAL; + internal const string CONNECTRETRYINTERVAL = "connectretryinterval"; + + //internal const string CurrentLanguage = LANGUAGE; + internal const string LANGUAGE = "language"; + + //internal const string OraDataSource = SERVER; + //internal const string SqlDataSource = ADDR + "," + ADDRESS + "," + SERVER + "," + NETWORKADDRESS; + internal const string ADDR = "addr"; + internal const string ADDRESS = "address"; + internal const string SERVER = "server"; + internal const string NETWORKADDRESS = "network address"; + + //internal const string InitialCatalog = DATABASE; + internal const string DATABASE = "database"; + + //internal const string IntegratedSecurity = TRUSTEDCONNECTION; + internal const string TRUSTEDCONNECTION = "trusted_connection"; // underscore introduced in everett + + //internal const string LoadBalanceTimeout = ConnectionLifetime; + internal const string ConnectionLifetime = "connection lifetime"; + + //internal const string MultipleActiveResultSets = MULTIPLEACTIVERESULTSETS; + internal const string MULTIPLEACTIVERESULTSETS = "multipleactiveresultsets"; + + //internal const string MultiSubnetFailover = MULTISUBNETFAILOVER; + internal const string MULTISUBNETFAILOVER = "multisubnetfailover"; + + //internal const string NetworkLibrary = NET + "," + NETWORK; + internal const string NET = "net"; + internal const string NETWORK = "network"; + + //internal const string PoolBlockingPeriod = POOLBLOCKINGPERIOD; + internal const string POOLBLOCKINGPERIOD = "poolblockingperiod"; + + //internal const string Password = Pwd; + internal const string Pwd = "pwd"; + + //internal const string PersistSecurityInfo = PERSISTSECURITYINFO; + internal const string PERSISTSECURITYINFO = "persistsecurityinfo"; + + //internal const string TrustServerCertificate = TRUSTSERVERCERTIFICATE; + internal const string TRUSTSERVERCERTIFICATE = "trustservercertificate"; + + //internal const string UserID = UID + "," + User; + internal const string UID = "uid"; + internal const string User = "user"; + + //internal const string WorkstationID = WSID; + internal const string WSID = "wsid"; + + //internal const string server SPNs + internal const string ServerSPN = "ServerSPN"; + internal const string FailoverPartnerSPN = "FailoverPartnerSPN"; + } +} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs index 0968e41dee..bcb48d4f4e 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs @@ -950,215 +950,9 @@ internal static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(st #endregion } - internal static class DbConnectionStringDefaults - { - internal const ApplicationIntent ApplicationIntent = Microsoft.Data.SqlClient.ApplicationIntent.ReadWrite; - internal const string ApplicationName = -#if NETFRAMEWORK - "Framework Microsoft SqlClient Data Provider"; -#else - "Core Microsoft SqlClient Data Provider"; -#endif - internal const string AttachDBFilename = ""; - internal const int CommandTimeout = 30; - internal const int ConnectTimeout = 15; - internal const bool ContextConnection = false; - -#if NETFRAMEWORK - internal const bool ConnectionReset = true; - internal static readonly bool TransparentNetworkIPResolution = !LocalAppContextSwitches.DisableTNIRByDefault; - internal const string NetworkLibrary = ""; -#endif - internal const string CurrentLanguage = ""; - internal const string DataSource = ""; - internal static readonly SqlConnectionEncryptOption Encrypt = SqlConnectionEncryptOption.Mandatory; - internal const string HostNameInCertificate = ""; - internal const string ServerCertificate = ""; - internal const bool Enlist = true; - internal const string FailoverPartner = ""; - internal const string InitialCatalog = ""; - internal const bool IntegratedSecurity = false; - internal const int LoadBalanceTimeout = 0; // default of 0 means don't use - internal const bool MultipleActiveResultSets = false; - internal const bool MultiSubnetFailover = false; - internal const int MaxPoolSize = 100; - internal const int MinPoolSize = 0; - internal const int PacketSize = 8000; - internal const string Password = ""; - internal const bool PersistSecurityInfo = false; - internal const bool Pooling = true; - internal const bool TrustServerCertificate = false; - internal const string TypeSystemVersion = "Latest"; - internal const string UserID = ""; - internal const bool UserInstance = false; - internal const bool Replication = false; - internal const string WorkstationID = ""; - internal const string TransactionBinding = "Implicit Unbind"; - internal const int ConnectRetryCount = 1; - internal const int ConnectRetryInterval = 10; - internal static readonly SqlAuthenticationMethod Authentication = SqlAuthenticationMethod.NotSpecified; - internal const SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled; - internal const string EnclaveAttestationUrl = ""; - internal const SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified; - internal const SqlConnectionIPAddressPreference IPAddressPreference = SqlConnectionIPAddressPreference.IPv4First; - internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto; - internal const string ServerSPN = ""; - internal const string FailoverPartnerSPN = ""; - } - - internal static class DbConnectionStringKeywords - { -#if NETFRAMEWORK - // Odbc - internal const string Driver = "Driver"; - internal const string Dsn = "Dsn"; - internal const string FileDsn = "FileDsn"; - internal const string SaveFile = "SaveFile"; - - // OleDb - internal const string FileName = "File Name"; - internal const string OleDbServices = "OLE DB Services"; - internal const string Provider = "Provider"; - - // OracleClient - internal const string Unicode = "Unicode"; - internal const string OmitOracleConnectionName = "Omit Oracle Connection Name"; -#endif - // SqlClient - internal const string ApplicationIntent = "Application Intent"; - internal const string ApplicationName = "Application Name"; - internal const string AttachDBFilename = "AttachDbFilename"; - internal const string ConnectTimeout = "Connect Timeout"; - internal const string CommandTimeout = "Command Timeout"; - internal const string ConnectionReset = "Connection Reset"; - internal const string ContextConnection = "Context Connection"; - internal const string CurrentLanguage = "Current Language"; - internal const string Encrypt = "Encrypt"; - internal const string HostNameInCertificate = "Host Name In Certificate"; - internal const string ServerCertificate = "Server Certificate"; - internal const string FailoverPartner = "Failover Partner"; - internal const string InitialCatalog = "Initial Catalog"; - internal const string MultipleActiveResultSets = "Multiple Active Result Sets"; - internal const string MultiSubnetFailover = "Multi Subnet Failover"; - internal const string NetworkLibrary = "Network Library"; - internal const string PacketSize = "Packet Size"; - internal const string Replication = "Replication"; - internal const string TransactionBinding = "Transaction Binding"; - internal const string TrustServerCertificate = "Trust Server Certificate"; - internal const string TypeSystemVersion = "Type System Version"; - internal const string UserInstance = "User Instance"; - internal const string WorkstationID = "Workstation ID"; - internal const string ConnectRetryCount = "Connect Retry Count"; - internal const string ConnectRetryInterval = "Connect Retry Interval"; - internal const string Authentication = "Authentication"; - internal const string ColumnEncryptionSetting = "Column Encryption Setting"; - internal const string EnclaveAttestationUrl = "Enclave Attestation Url"; - internal const string AttestationProtocol = "Attestation Protocol"; - internal const string IPAddressPreference = "IP Address Preference"; - internal const string ServerSPN = "Server SPN"; - internal const string FailoverPartnerSPN = "Failover Partner SPN"; - internal const string TransparentNetworkIPResolution = "Transparent Network IP Resolution"; - - // common keywords (OleDb, OracleClient, SqlClient) - internal const string DataSource = "Data Source"; - internal const string IntegratedSecurity = "Integrated Security"; - internal const string Password = "Password"; - internal const string PersistSecurityInfo = "Persist Security Info"; - internal const string UserID = "User ID"; - - // managed pooling (OracleClient, SqlClient) - internal const string Enlist = "Enlist"; - internal const string LoadBalanceTimeout = "Load Balance Timeout"; - internal const string MaxPoolSize = "Max Pool Size"; - internal const string Pooling = "Pooling"; - internal const string MinPoolSize = "Min Pool Size"; - internal const string PoolBlockingPeriod = "Pool Blocking Period"; - } - - internal static class DbConnectionStringSynonyms - { - //internal const string TransparentNetworkIPResolution = TRANSPARENTNETWORKIPRESOLUTION; - internal const string TRANSPARENTNETWORKIPRESOLUTION = "transparentnetworkipresolution"; - - //internal const string ApplicationName = APP; - internal const string APP = "app"; - - // internal const string IPAddressPreference = IPADDRESSPREFERENCE; - internal const string IPADDRESSPREFERENCE = "ipaddresspreference"; - - //internal const string ApplicationIntent = APPLICATIONINTENT; - internal const string APPLICATIONINTENT = "applicationintent"; - - //internal const string AttachDBFilename = EXTENDEDPROPERTIES+","+INITIALFILENAME; - internal const string EXTENDEDPROPERTIES = "extended properties"; - internal const string INITIALFILENAME = "initial file name"; - - // internal const string HostNameInCertificate = HOSTNAMEINCERTIFICATE; - internal const string HOSTNAMEINCERTIFICATE = "hostnameincertificate"; - - // internal const string ServerCertificate = SERVERCERTIFICATE; - internal const string SERVERCERTIFICATE = "servercertificate"; - - //internal const string ConnectTimeout = CONNECTIONTIMEOUT+","+TIMEOUT; - internal const string CONNECTIONTIMEOUT = "connection timeout"; - internal const string TIMEOUT = "timeout"; + - //internal const string ConnectRetryCount = CONNECTRETRYCOUNT; - internal const string CONNECTRETRYCOUNT = "connectretrycount"; + - //internal const string ConnectRetryInterval = CONNECTRETRYINTERVAL; - internal const string CONNECTRETRYINTERVAL = "connectretryinterval"; - - //internal const string CurrentLanguage = LANGUAGE; - internal const string LANGUAGE = "language"; - - //internal const string OraDataSource = SERVER; - //internal const string SqlDataSource = ADDR+","+ADDRESS+","+SERVER+","+NETWORKADDRESS; - internal const string ADDR = "addr"; - internal const string ADDRESS = "address"; - internal const string SERVER = "server"; - internal const string NETWORKADDRESS = "network address"; - - //internal const string InitialCatalog = DATABASE; - internal const string DATABASE = "database"; - - //internal const string IntegratedSecurity = TRUSTEDCONNECTION; - internal const string TRUSTEDCONNECTION = "trusted_connection"; // underscore introduced in everett - - //internal const string LoadBalanceTimeout = ConnectionLifetime; - internal const string ConnectionLifetime = "connection lifetime"; - - //internal const string MultipleActiveResultSets = MULTIPLEACTIVERESULTSETS; - internal const string MULTIPLEACTIVERESULTSETS = "multipleactiveresultsets"; - - //internal const string MultiSubnetFailover = MULTISUBNETFAILOVER; - internal const string MULTISUBNETFAILOVER = "multisubnetfailover"; - - //internal const string NetworkLibrary = NET+","+NETWORK; - internal const string NET = "net"; - internal const string NETWORK = "network"; - - //internal const string PoolBlockingPeriod = POOLBLOCKINGPERIOD; - internal const string POOLBLOCKINGPERIOD = "poolblockingperiod"; - - //internal const string Password = Pwd; - internal const string Pwd = "pwd"; - - //internal const string PersistSecurityInfo = PERSISTSECURITYINFO; - internal const string PERSISTSECURITYINFO = "persistsecurityinfo"; - - //internal const string TrustServerCertificate = TRUSTSERVERCERTIFICATE; - internal const string TRUSTSERVERCERTIFICATE = "trustservercertificate"; - - //internal const string UserID = UID+","+User; - internal const string UID = "uid"; - internal const string User = "user"; - - //internal const string WorkstationID = WSID; - internal const string WSID = "wsid"; - - //internal const string server SPNs - internal const string ServerSPN = "ServerSPN"; - internal const string FailoverPartnerSPN = "FailoverPartnerSPN"; - } + } From 9b8cfb20e2b9b6c3d048769c62426344ce1df1c8 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Thu, 3 Apr 2025 12:23:32 -0500 Subject: [PATCH 2/3] Wire up moved files --- .../netcore/src/Microsoft.Data.SqlClient.csproj | 9 +++++++++ .../Data/Common/DbConnectionOptions.cs | 1 + .../netfx/src/Microsoft.Data.SqlClient.csproj | 9 +++++++++ .../Microsoft/Data/Common/DBConnectionString.cs | 17 +++++++++-------- .../Data/Common/DbConnectionOptions.cs | 1 + .../src/Microsoft/Data/Common/AdapterUtil.cs | 2 ++ .../Data/Common/DbConnectionOptions.Common.cs | 1 + .../Data/Common/DbConnectionStringCommon.cs | 1 + .../ActiveDirectoryAuthenticationProvider.cs | 5 +++-- .../Data/SqlClient/SqlConnectionString.cs | 4 ++++ .../SqlClient/SqlConnectionStringBuilder.cs | 1 + .../src/Microsoft/Data/SqlClient/TdsEnums.cs | 3 ++- 12 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index c35899a762..b8df3c9fab 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -53,6 +53,15 @@ Microsoft\Data\Common\BitConverterCompatible.cs + + Microsoft\Data\Common\ConnectionString\DbConnectionStringDefaults.cs + + + Microsoft\Data\Common\ConnectionString\DbConnectionStringKeywords.cs + + + Microsoft\Data\Common\ConnectionString\DbConnectionStringSynonyms.cs + Microsoft\Data\Common\DbConnectionOptions.Common.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionOptions.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionOptions.cs index 759696d471..443b7e6734 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionOptions.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionOptions.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Text; +using Microsoft.Data.Common.ConnectionString; namespace Microsoft.Data.Common { diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 8099e9ff71..c380ceb73f 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -235,6 +235,15 @@ Microsoft\Data\Common\BitConverterCompatible.cs + + Microsoft\Data\Common\ConnectionString\DbConnectionStringDefaults.cs + + + Microsoft\Data\Common\ConnectionString\DbConnectionStringKeywords.cs + + + Microsoft\Data\Common\ConnectionString\DbConnectionStringSynonyms.cs + Microsoft\Data\Common\DbConnectionStringCommon.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DBConnectionString.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DBConnectionString.cs index 66c46602c5..4fe523ae2f 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DBConnectionString.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DBConnectionString.cs @@ -2,16 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Text; +using Microsoft.Data.Common.ConnectionString; +using Microsoft.Data.SqlClient; + namespace Microsoft.Data.Common { - - using System; - using System.Collections.Generic; - using System.Data; - using System.Diagnostics; - using System.Text; - using Microsoft.Data.SqlClient; - [Serializable] // MDAC 83147 internal sealed class DBConnectionString { @@ -19,6 +19,7 @@ internal sealed class DBConnectionString // used by permission classes so it is much easier to verify correctness // when not worried about the class being modified during execution + // @TODO: Remove in favor of DbConnectionStringKeywords private static class KEY { internal const string Password = DbConnectionStringKeywords.Password; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionOptions.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionOptions.cs index e240c3d822..b0507ea83e 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionOptions.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionOptions.cs @@ -6,6 +6,7 @@ using System.Runtime.Versioning; using System.Security; using System.Text; +using Microsoft.Data.Common.ConnectionString; namespace Microsoft.Data.Common { diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs index f51723ace2..c8dcdd6934 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs @@ -18,6 +18,7 @@ using System.Threading; using System.Threading.Tasks; using System.Transactions; +using Microsoft.Data.Common.ConnectionString; using Microsoft.Data.SqlClient; using IsolationLevel = System.Data.IsolationLevel; using Microsoft.Identity.Client; @@ -47,6 +48,7 @@ internal static partial class ADP { // NOTE: Initializing a Task in SQL CLR requires the "UNSAFE" permission set (http://msdn.microsoft.com/en-us/library/ms172338.aspx) // Therefore we are lazily initializing these Tasks to avoid forcing customers to use the "UNSAFE" set when they are actually using no Async features + // @TODO: These are not necessary because the TPL has optimized commonly used task return values like true and false. private static Task s_trueTask; internal static Task TrueTask => s_trueTask ??= Task.FromResult(true); diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionOptions.Common.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionOptions.Common.cs index f72eb5ee59..f9e83b0120 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionOptions.Common.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionOptions.Common.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Text; using System.Text.RegularExpressions; +using Microsoft.Data.Common.ConnectionString; using Microsoft.Data.SqlClient; namespace Microsoft.Data.Common diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs index bcb48d4f4e..829b2627a8 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; +using Microsoft.Data.Common.ConnectionString; using Microsoft.Data.SqlClient; namespace Microsoft.Data.Common diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs index 00ef72db6d..ddfe34b8a9 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Azure.Core; using Azure.Identity; +using Microsoft.Data.Common.ConnectionString; using Microsoft.Extensions.Caching.Memory; using Microsoft.Identity.Client; using Microsoft.Identity.Client.Extensibility; @@ -553,7 +554,7 @@ private IPublicClientApplication CreateClientAppInstance(PublicClientAppKey publ { publicClientApplication = PublicClientApplicationBuilder.Create(publicClientAppKey._applicationClientId) .WithAuthority(publicClientAppKey._authority) - .WithClientName(Common.DbConnectionStringDefaults.ApplicationName) + .WithClientName(DbConnectionStringDefaults.ApplicationName) .WithClientVersion(Common.ADP.GetAssemblyVersion().ToString()) .WithRedirectUri(publicClientAppKey._redirectUri) .WithParentActivityOrWindow(_iWin32WindowFunc) @@ -564,7 +565,7 @@ private IPublicClientApplication CreateClientAppInstance(PublicClientAppKey publ { publicClientApplication = PublicClientApplicationBuilder.Create(publicClientAppKey._applicationClientId) .WithAuthority(publicClientAppKey._authority) - .WithClientName(Common.DbConnectionStringDefaults.ApplicationName) + .WithClientName(DbConnectionStringDefaults.ApplicationName) .WithClientVersion(Common.ADP.GetAssemblyVersion().ToString()) .WithRedirectUri(publicClientAppKey._redirectUri) .Build(); diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs index 58b34fd287..5b0f33c261 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs @@ -13,6 +13,7 @@ using System.Security; using System.Security.Permissions; using Microsoft.Data.Common; +using Microsoft.Data.Common.ConnectionString; using Microsoft.Data.SqlClient.LocalDb; namespace Microsoft.Data.SqlClient @@ -23,6 +24,7 @@ internal sealed class SqlConnectionString : DbConnectionOptions // used by pooling classes so it is much easier to verify correctness // when not worried about the class being modified during execution + // @TODO: Remove this in favor of using DbConnectionStringDefaults?? internal static class DEFAULT { internal const ApplicationIntent ApplicationIntent = DbConnectionStringDefaults.ApplicationIntent; @@ -71,6 +73,7 @@ internal static class DEFAULT #endif // NETFRAMEWORK } + // @TODO: Remove in favor of DbConnectionStringKeywords // SqlConnection ConnectionString Options internal static class KEY { @@ -126,6 +129,7 @@ internal static class KEY #endif // NETFRAMEWORK } + // @TODO: Remove in favor DbConnectionStringSynonyms // Constant for the number of duplicate options in the connection string private static class SYNONYM { diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs index 4ed5c59198..2bc6e1e43b 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs @@ -15,6 +15,7 @@ using System.Globalization; using System.Reflection; using Microsoft.Data.Common; +using Microsoft.Data.Common.ConnectionString; namespace Microsoft.Data.SqlClient { diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsEnums.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsEnums.cs index 4d3fc9218b..2075edf1df 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsEnums.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsEnums.cs @@ -4,6 +4,7 @@ using System; using System.Data; +using Microsoft.Data.Common.ConnectionString; namespace Microsoft.Data.SqlClient { @@ -14,7 +15,7 @@ internal static class TdsEnums // internal tdsparser constants - public const string SQL_PROVIDER_NAME = Common.DbConnectionStringDefaults.ApplicationName; + public const string SQL_PROVIDER_NAME = DbConnectionStringDefaults.ApplicationName; public static readonly decimal SQL_SMALL_MONEY_MIN = new(-214748.3648); public static readonly decimal SQL_SMALL_MONEY_MAX = new(214748.3647); From e9d65236aaebf0489109c9f3a2a877f1b021d260 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Thu, 3 Apr 2025 12:51:25 -0500 Subject: [PATCH 3/3] Splitting remaining common class, moving "common" class to ConnectionString namespace and renaming to sync class/file name. --- .../src/Microsoft.Data.SqlClient.csproj | 15 +- .../Microsoft/Data/SqlClient/SqlConnection.cs | 24 +- .../netfx/src/Microsoft.Data.SqlClient.csproj | 13 +- .../Microsoft/Data/SqlClient/SqlConnection.cs | 24 +- .../AttestationProtocolUtilities.cs | 148 +++++++ .../DbConnectionStringUtilities.cs} | 369 +----------------- .../IpAddressPreferenceUtilities.cs | 115 ++++++ .../ConnectionString/PoolBlockingUtilities.cs | 136 +++++++ .../Data/SqlClient/SqlConnectionString.cs | 22 +- .../SqlClient/SqlConnectionStringBuilder.cs | 63 +-- .../src/Microsoft/Data/SqlClient/SqlUtil.cs | 2 +- 11 files changed, 492 insertions(+), 439 deletions(-) create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/AttestationProtocolUtilities.cs rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/{DbConnectionStringCommon.cs => ConnectionString/DbConnectionStringUtilities.cs} (62%) create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/IpAddressPreferenceUtilities.cs create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/PoolBlockingUtilities.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index b8df3c9fab..b56e1be1b6 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -53,6 +53,9 @@ Microsoft\Data\Common\BitConverterCompatible.cs + + Microsoft\Data\Common\ConnectionString\AttestationProtocolUtilities.cs + Microsoft\Data\Common\ConnectionString\DbConnectionStringDefaults.cs @@ -62,12 +65,18 @@ Microsoft\Data\Common\ConnectionString\DbConnectionStringSynonyms.cs + + Microsoft\Data\Common\ConnectionString\DbConnectionStringUtilities.cs + + + Microsoft\Data\Common\ConnectionString\IpAddressPreferenceUtilities.cs + + + Microsoft\Data\Common\ConnectionString\PoolBlockingUtilities.cs + Microsoft\Data\Common\DbConnectionOptions.Common.cs - - Microsoft\Data\Common\DbConnectionStringCommon.cs - Microsoft\Data\Common\MultipartIdentifier.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs index f0fc806ee0..fcb97953ab 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -194,19 +194,19 @@ public SqlConnection(string connectionString, SqlCredential credential) : this() } else if (UsesActiveDirectoryManagedIdentity(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryManagedIdentityString); + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringUtilities.ActiveDirectoryManagedIdentityString); } else if (UsesActiveDirectoryMSI(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryMSIString); + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringUtilities.ActiveDirectoryMSIString); } else if (UsesActiveDirectoryDefault(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringUtilities.ActiveDirectoryDefaultString); } else if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringUtilities.ActiveDirectoryWorkloadIdentityString); } Credential = credential; @@ -621,19 +621,19 @@ public override string ConnectionString } else if (UsesActiveDirectoryManagedIdentity(connectionOptions)) { - throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryManagedIdentityString); + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringUtilities.ActiveDirectoryManagedIdentityString); } else if (UsesActiveDirectoryMSI(connectionOptions)) { - throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryMSIString); + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringUtilities.ActiveDirectoryMSIString); } else if (UsesActiveDirectoryDefault(connectionOptions)) { - throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringUtilities.ActiveDirectoryDefaultString); } else if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) { - throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringUtilities.ActiveDirectoryWorkloadIdentityString); } CheckAndThrowOnInvalidCombinationOfConnectionStringAndSqlCredential(connectionOptions); @@ -1005,19 +1005,19 @@ public SqlCredential Credential } else if (UsesActiveDirectoryManagedIdentity(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryManagedIdentityString); + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringUtilities.ActiveDirectoryManagedIdentityString); } else if (UsesActiveDirectoryMSI(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryMSIString); + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringUtilities.ActiveDirectoryMSIString); } else if (UsesActiveDirectoryDefault(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringUtilities.ActiveDirectoryDefaultString); } else if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringUtilities.ActiveDirectoryWorkloadIdentityString); } CheckAndThrowOnInvalidCombinationOfConnectionStringAndSqlCredential(connectionOptions); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index c380ceb73f..d33af1916a 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -235,6 +235,9 @@ Microsoft\Data\Common\BitConverterCompatible.cs + + Microsoft\Data\Common\ConnectionString\AttestationProtocolUtilities.cs + Microsoft\Data\Common\ConnectionString\DbConnectionStringDefaults.cs @@ -244,8 +247,14 @@ Microsoft\Data\Common\ConnectionString\DbConnectionStringSynonyms.cs - - Microsoft\Data\Common\DbConnectionStringCommon.cs + + Microsoft\Data\Common\ConnectionString\DbConnectionStringUtilities.cs + + + Microsoft\Data\Common\ConnectionString\IpAddressPreferenceUtilities.cs + + + Microsoft\Data\Common\ConnectionString\PoolBlockingUtilities.cs Microsoft\Data\Common\DbConnectionOptions.Common.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs index 02eff9971d..78b431a1c9 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -388,22 +388,22 @@ public SqlConnection(string connectionString, SqlCredential credential) : this() if (UsesActiveDirectoryManagedIdentity(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryManagedIdentityString); + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringUtilities.ActiveDirectoryManagedIdentityString); } if (UsesActiveDirectoryMSI(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryMSIString); + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringUtilities.ActiveDirectoryMSIString); } if (UsesActiveDirectoryDefault(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringUtilities.ActiveDirectoryDefaultString); } if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + throw SQL.SettingCredentialWithNonInteractiveArgument(DbConnectionStringUtilities.ActiveDirectoryWorkloadIdentityString); } Credential = credential; @@ -823,19 +823,19 @@ override public string ConnectionString } else if (UsesActiveDirectoryManagedIdentity(connectionOptions)) { - throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryManagedIdentityString); + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringUtilities.ActiveDirectoryManagedIdentityString); } else if (UsesActiveDirectoryMSI(connectionOptions)) { - throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryMSIString); + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringUtilities.ActiveDirectoryMSIString); } else if (UsesActiveDirectoryDefault(connectionOptions)) { - throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringUtilities.ActiveDirectoryDefaultString); } else if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) { - throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + throw SQL.SettingNonInteractiveWithCredential(DbConnectionStringUtilities.ActiveDirectoryWorkloadIdentityString); } CheckAndThrowOnInvalidCombinationOfConnectionStringAndSqlCredential(connectionOptions); @@ -1176,19 +1176,19 @@ public SqlCredential Credential } else if (UsesActiveDirectoryManagedIdentity(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryManagedIdentityString); + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringUtilities.ActiveDirectoryManagedIdentityString); } else if (UsesActiveDirectoryMSI(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryMSIString); + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringUtilities.ActiveDirectoryMSIString); } else if (UsesActiveDirectoryDefault(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringUtilities.ActiveDirectoryDefaultString); } else if (UsesActiveDirectoryWorkloadIdentity(connectionOptions)) { - throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + throw SQL.SettingCredentialWithNonInteractiveInvalid(DbConnectionStringUtilities.ActiveDirectoryWorkloadIdentityString); } CheckAndThrowOnInvalidCombinationOfConnectionStringAndSqlCredential(connectionOptions); diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/AttestationProtocolUtilities.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/AttestationProtocolUtilities.cs new file mode 100644 index 0000000000..75e6eede3f --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/AttestationProtocolUtilities.cs @@ -0,0 +1,148 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using Microsoft.Data.SqlClient; + +namespace Microsoft.Data.Common.ConnectionString +{ + internal static class AttestationProtocolUtilities + { + /// + /// Convert a string value to the corresponding SqlConnectionAttestationProtocol + /// + /// + /// + /// + internal static bool TryConvertToAttestationProtocol(string value, out SqlConnectionAttestationProtocol result) + { + if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.HGS))) + { + result = SqlConnectionAttestationProtocol.HGS; + return true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.AAS))) + { + result = SqlConnectionAttestationProtocol.AAS; + return true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.None))) + { + result = SqlConnectionAttestationProtocol.None; + return true; + } + else + { + result = DbConnectionStringDefaults.AttestationProtocol; + return false; + } + } + + internal static bool IsValidAttestationProtocol(SqlConnectionAttestationProtocol value) + { + Debug.Assert(Enum.GetNames(typeof(SqlConnectionAttestationProtocol)).Length == 4, "SqlConnectionAttestationProtocol enum has changed, update needed"); + return value == SqlConnectionAttestationProtocol.NotSpecified + || value == SqlConnectionAttestationProtocol.HGS + || value == SqlConnectionAttestationProtocol.AAS + || value == SqlConnectionAttestationProtocol.None; + } + + internal static string AttestationProtocolToString(SqlConnectionAttestationProtocol value) + { + Debug.Assert(IsValidAttestationProtocol(value), "value is not a valid attestation protocol"); + + return value switch + { + SqlConnectionAttestationProtocol.AAS => nameof(SqlConnectionAttestationProtocol.AAS), + SqlConnectionAttestationProtocol.HGS => nameof(SqlConnectionAttestationProtocol.HGS), + SqlConnectionAttestationProtocol.None => nameof(SqlConnectionAttestationProtocol.None), + _ => null + }; + } + + internal static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(string keyword, object value) + { + if (value == null) + { + return DbConnectionStringDefaults.AttestationProtocol; + } + + if (value is string sValue) + { + // try again after remove leading & trailing whitespaces. + sValue = sValue.Trim(); + if (TryConvertToAttestationProtocol(sValue, out SqlConnectionAttestationProtocol result)) + { + return result; + } + + // string values must be valid + throw ADP.InvalidConnectionOptionValue(keyword); + } + else + { + // the value is not string, try other options + SqlConnectionAttestationProtocol eValue; + + if (value is SqlConnectionAttestationProtocol protocol) + { + eValue = protocol; + } + else if (value.GetType().IsEnum) + { + // explicitly block scenarios in which user tries to use wrong enum types, like: + // builder["SqlConnectionAttestationProtocol"] = EnvironmentVariableTarget.Process; + // workaround: explicitly cast non-SqlConnectionAttestationProtocol enums to int + throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), null); + } + else + { + try + { + // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest + eValue = (SqlConnectionAttestationProtocol)Enum.ToObject(typeof(SqlConnectionAttestationProtocol), value); + } + catch (ArgumentException e) + { + // to be consistent with the messages we send in case of wrong type usage, replace + // the error with our exception, and keep the original one as inner one for troubleshooting + throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), e); + } + } + + if (IsValidAttestationProtocol(eValue)) + { + return eValue; + } + else + { + throw ADP.InvalidEnumerationValue(typeof(SqlConnectionAttestationProtocol), (int)eValue); + } + } + } + + internal static SqlConnectionEncryptOption ConvertToSqlConnectionEncryptOption(string keyword, object value) + { + if (value is null) + { + return DbConnectionStringDefaults.Encrypt; + } + else if(value is SqlConnectionEncryptOption eValue) + { + return eValue; + } + else if (value is string sValue) + { + return SqlConnectionEncryptOption.Parse(sValue); + } + else if(value is bool bValue) + { + return SqlConnectionEncryptOption.Parse(bValue); + } + + throw ADP.InvalidConnectionOptionValue(keyword); + } + } +} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringUtilities.cs similarity index 62% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringUtilities.cs index 829b2627a8..927b2e62a6 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/DbConnectionStringUtilities.cs @@ -11,7 +11,7 @@ namespace Microsoft.Data.Common { - internal static class DbConnectionStringBuilderUtil + internal static class DbConnectionStringUtilities { internal static bool ConvertToBoolean(object value) { @@ -103,131 +103,6 @@ internal static string ConvertToString(object value) } } - #region <> - internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result) - { - Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); - Debug.Assert(value != null, "TryConvertToPoolBlockingPeriod(null,...)"); - - if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.Auto))) - { - result = PoolBlockingPeriod.Auto; - return true; - } - else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.AlwaysBlock))) - { - result = PoolBlockingPeriod.AlwaysBlock; - return true; - } - else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.NeverBlock))) - { - result = PoolBlockingPeriod.NeverBlock; - return true; - } - else - { - result = DbConnectionStringDefaults.PoolBlockingPeriod; - return false; - } - } - - internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value) - { - Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); - return value == PoolBlockingPeriod.Auto || value == PoolBlockingPeriod.AlwaysBlock || value == PoolBlockingPeriod.NeverBlock; - } - - internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value) - { - Debug.Assert(IsValidPoolBlockingPeriodValue(value)); - - return value switch - { - PoolBlockingPeriod.AlwaysBlock => nameof(PoolBlockingPeriod.AlwaysBlock), - PoolBlockingPeriod.NeverBlock => nameof(PoolBlockingPeriod.NeverBlock), - _ => nameof(PoolBlockingPeriod.Auto), - }; - } - - /// - /// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is: - /// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer - /// * if the value is from type PoolBlockingPeriod, it will be used as is - /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum - /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException - /// - /// in any case above, if the converted value is out of valid range, the method raises ArgumentOutOfRangeException. - /// - /// PoolBlockingPeriod value in the valid range - internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value) - { - Debug.Assert(value != null, "ConvertToPoolBlockingPeriod(null)"); - if (value is string sValue) - { - // We could use Enum.TryParse here, but it accepts value combinations like - // "ReadOnly, ReadWrite" which are unwelcome here - // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method. - - if (TryConvertToPoolBlockingPeriod(sValue, out PoolBlockingPeriod result)) - { - return result; - } - - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToPoolBlockingPeriod(sValue, out result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - PoolBlockingPeriod eValue; - - if (value is PoolBlockingPeriod period) - { - // quick path for the most common case - eValue = period; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-PoolBlockingPeriod enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e); - } - } - - // ensure value is in valid range - if (IsValidPoolBlockingPeriodValue(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue); - } - } - } - #endregion - internal static bool TryConvertToApplicationIntent(string value, out ApplicationIntent result) { Debug.Assert(Enum.GetNames(typeof(ApplicationIntent)).Length == 2, "ApplicationIntent enum has changed, update needed"); @@ -707,248 +582,6 @@ internal static SqlConnectionColumnEncryptionSetting ConvertToColumnEncryptionSe } } } - - #region <> - /// - /// Convert a string value to the corresponding SqlConnectionAttestationProtocol - /// - /// - /// - /// - internal static bool TryConvertToAttestationProtocol(string value, out SqlConnectionAttestationProtocol result) - { - if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.HGS))) - { - result = SqlConnectionAttestationProtocol.HGS; - return true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.AAS))) - { - result = SqlConnectionAttestationProtocol.AAS; - return true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.None))) - { - result = SqlConnectionAttestationProtocol.None; - return true; - } - else - { - result = DbConnectionStringDefaults.AttestationProtocol; - return false; - } - } - - internal static bool IsValidAttestationProtocol(SqlConnectionAttestationProtocol value) - { - Debug.Assert(Enum.GetNames(typeof(SqlConnectionAttestationProtocol)).Length == 4, "SqlConnectionAttestationProtocol enum has changed, update needed"); - return value == SqlConnectionAttestationProtocol.NotSpecified - || value == SqlConnectionAttestationProtocol.HGS - || value == SqlConnectionAttestationProtocol.AAS - || value == SqlConnectionAttestationProtocol.None; - } - - internal static string AttestationProtocolToString(SqlConnectionAttestationProtocol value) - { - Debug.Assert(IsValidAttestationProtocol(value), "value is not a valid attestation protocol"); - - return value switch - { - SqlConnectionAttestationProtocol.AAS => nameof(SqlConnectionAttestationProtocol.AAS), - SqlConnectionAttestationProtocol.HGS => nameof(SqlConnectionAttestationProtocol.HGS), - SqlConnectionAttestationProtocol.None => nameof(SqlConnectionAttestationProtocol.None), - _ => null - }; - } - - internal static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(string keyword, object value) - { - if (value == null) - { - return DbConnectionStringDefaults.AttestationProtocol; - } - - if (value is string sValue) - { - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToAttestationProtocol(sValue, out SqlConnectionAttestationProtocol result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - SqlConnectionAttestationProtocol eValue; - - if (value is SqlConnectionAttestationProtocol protocol) - { - eValue = protocol; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["SqlConnectionAttestationProtocol"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-SqlConnectionAttestationProtocol enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (SqlConnectionAttestationProtocol)Enum.ToObject(typeof(SqlConnectionAttestationProtocol), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), e); - } - } - - if (IsValidAttestationProtocol(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(SqlConnectionAttestationProtocol), (int)eValue); - } - } - } - - internal static SqlConnectionEncryptOption ConvertToSqlConnectionEncryptOption(string keyword, object value) - { - if (value is null) - { - return DbConnectionStringDefaults.Encrypt; - } - else if(value is SqlConnectionEncryptOption eValue) - { - return eValue; - } - else if (value is string sValue) - { - return SqlConnectionEncryptOption.Parse(sValue); - } - else if(value is bool bValue) - { - return SqlConnectionEncryptOption.Parse(bValue); - } - - throw ADP.InvalidConnectionOptionValue(keyword); - } - - #endregion - - #region <> - /// - /// IP Address Preference. - /// - private readonly static Dictionary s_preferenceNames = new(StringComparer.InvariantCultureIgnoreCase); - - static DbConnectionStringBuilderUtil() - { - foreach (SqlConnectionIPAddressPreference item in Enum.GetValues(typeof(SqlConnectionIPAddressPreference))) - { - s_preferenceNames.Add(item.ToString(), item); - } - } - - /// - /// Convert a string value to the corresponding IPAddressPreference. - /// - /// The string representation of the enumeration name to convert. - /// When this method returns, `result` contains an object of type `SqlConnectionIPAddressPreference` whose value is represented by `value` if the operation succeeds. - /// If the parse operation fails, `result` contains the default value of the `SqlConnectionIPAddressPreference` type. - /// `true` if the value parameter was converted successfully; otherwise, `false`. - internal static bool TryConvertToIPAddressPreference(string value, out SqlConnectionIPAddressPreference result) - { - if (!s_preferenceNames.TryGetValue(value, out result)) - { - result = DbConnectionStringDefaults.IPAddressPreference; - return false; - } - return true; - } - - /// - /// Verifies if the `value` is defined in the expected Enum. - /// - internal static bool IsValidIPAddressPreference(SqlConnectionIPAddressPreference value) - => value == SqlConnectionIPAddressPreference.IPv4First - || value == SqlConnectionIPAddressPreference.IPv6First - || value == SqlConnectionIPAddressPreference.UsePlatformDefault; - - internal static string IPAddressPreferenceToString(SqlConnectionIPAddressPreference value) - => Enum.GetName(typeof(SqlConnectionIPAddressPreference), value); - - internal static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(string keyword, object value) - { - if (value is null) - { - return DbConnectionStringDefaults.IPAddressPreference; // IPv4First - } - - if (value is string sValue) - { - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToIPAddressPreference(sValue, out SqlConnectionIPAddressPreference result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - SqlConnectionIPAddressPreference eValue; - - if (value is SqlConnectionIPAddressPreference preference) - { - eValue = preference; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["SqlConnectionIPAddressPreference"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-SqlConnectionIPAddressPreference enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (SqlConnectionIPAddressPreference)Enum.ToObject(typeof(SqlConnectionIPAddressPreference), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), e); - } - } - - if (IsValidIPAddressPreference(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(SqlConnectionIPAddressPreference), (int)eValue); - } - } - } - #endregion } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/IpAddressPreferenceUtilities.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/IpAddressPreferenceUtilities.cs new file mode 100644 index 0000000000..a9e59dfe2b --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/IpAddressPreferenceUtilities.cs @@ -0,0 +1,115 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using Microsoft.Data.SqlClient; + +namespace Microsoft.Data.Common.ConnectionString +{ + internal static class IpAddressPreferenceUtilities + { + /// + /// IP Address Preference. + /// + private readonly static Dictionary s_preferenceNames = new(StringComparer.InvariantCultureIgnoreCase); + + static IpAddressPreferenceUtilities() + { + foreach (SqlConnectionIPAddressPreference item in Enum.GetValues(typeof(SqlConnectionIPAddressPreference))) + { + s_preferenceNames.Add(item.ToString(), item); + } + } + + /// + /// Convert a string value to the corresponding IPAddressPreference. + /// + /// The string representation of the enumeration name to convert. + /// When this method returns, `result` contains an object of type `SqlConnectionIPAddressPreference` whose value is represented by `value` if the operation succeeds. + /// If the parse operation fails, `result` contains the default value of the `SqlConnectionIPAddressPreference` type. + /// `true` if the value parameter was converted successfully; otherwise, `false`. + internal static bool TryConvertToIPAddressPreference(string value, out SqlConnectionIPAddressPreference result) + { + if (!s_preferenceNames.TryGetValue(value, out result)) + { + result = DbConnectionStringDefaults.IPAddressPreference; + return false; + } + return true; + } + + /// + /// Verifies if the `value` is defined in the expected Enum. + /// + internal static bool IsValidIPAddressPreference(SqlConnectionIPAddressPreference value) + => value == SqlConnectionIPAddressPreference.IPv4First + || value == SqlConnectionIPAddressPreference.IPv6First + || value == SqlConnectionIPAddressPreference.UsePlatformDefault; + + internal static string IPAddressPreferenceToString(SqlConnectionIPAddressPreference value) + => Enum.GetName(typeof(SqlConnectionIPAddressPreference), value); + + internal static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(string keyword, object value) + { + if (value is null) + { + return DbConnectionStringDefaults.IPAddressPreference; // IPv4First + } + + if (value is string sValue) + { + // try again after remove leading & trailing whitespaces. + sValue = sValue.Trim(); + if (TryConvertToIPAddressPreference(sValue, out SqlConnectionIPAddressPreference result)) + { + return result; + } + + // string values must be valid + throw ADP.InvalidConnectionOptionValue(keyword); + } + else + { + // the value is not string, try other options + SqlConnectionIPAddressPreference eValue; + + if (value is SqlConnectionIPAddressPreference preference) + { + eValue = preference; + } + else if (value.GetType().IsEnum) + { + // explicitly block scenarios in which user tries to use wrong enum types, like: + // builder["SqlConnectionIPAddressPreference"] = EnvironmentVariableTarget.Process; + // workaround: explicitly cast non-SqlConnectionIPAddressPreference enums to int + throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), null); + } + else + { + try + { + // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest + eValue = (SqlConnectionIPAddressPreference)Enum.ToObject(typeof(SqlConnectionIPAddressPreference), value); + } + catch (ArgumentException e) + { + // to be consistent with the messages we send in case of wrong type usage, replace + // the error with our exception, and keep the original one as inner one for troubleshooting + throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), e); + } + } + + if (IsValidIPAddressPreference(eValue)) + { + return eValue; + } + else + { + throw ADP.InvalidEnumerationValue(typeof(SqlConnectionIPAddressPreference), (int)eValue); + } + } + } + } +} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/PoolBlockingUtilities.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/PoolBlockingUtilities.cs new file mode 100644 index 0000000000..3a69271317 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/ConnectionString/PoolBlockingUtilities.cs @@ -0,0 +1,136 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using Microsoft.Data.SqlClient; + +namespace Microsoft.Data.Common.ConnectionString +{ + internal static class PoolBlockingUtilities + { + internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result) + { + Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); + Debug.Assert(value != null, "TryConvertToPoolBlockingPeriod(null,...)"); + + if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.Auto))) + { + result = PoolBlockingPeriod.Auto; + return true; + } + else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.AlwaysBlock))) + { + result = PoolBlockingPeriod.AlwaysBlock; + return true; + } + else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.NeverBlock))) + { + result = PoolBlockingPeriod.NeverBlock; + return true; + } + else + { + result = DbConnectionStringDefaults.PoolBlockingPeriod; + return false; + } + } + + internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value) + { + Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); + return value == PoolBlockingPeriod.Auto || value == PoolBlockingPeriod.AlwaysBlock || value == PoolBlockingPeriod.NeverBlock; + } + + internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value) + { + Debug.Assert(IsValidPoolBlockingPeriodValue(value)); + + return value switch + { + PoolBlockingPeriod.AlwaysBlock => nameof(PoolBlockingPeriod.AlwaysBlock), + PoolBlockingPeriod.NeverBlock => nameof(PoolBlockingPeriod.NeverBlock), + _ => nameof(PoolBlockingPeriod.Auto), + }; + } + + /// + /// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is: + /// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer + /// * if the value is from type PoolBlockingPeriod, it will be used as is + /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum + /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException + /// + /// in any case above, if the converted value is out of valid range, the method raises ArgumentOutOfRangeException. + /// + /// PoolBlockingPeriod value in the valid range + internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value) + { + Debug.Assert(value != null, "ConvertToPoolBlockingPeriod(null)"); + if (value is string sValue) + { + // We could use Enum.TryParse here, but it accepts value combinations like + // "ReadOnly, ReadWrite" which are unwelcome here + // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method. + + if (TryConvertToPoolBlockingPeriod(sValue, out PoolBlockingPeriod result)) + { + return result; + } + + // try again after remove leading & trailing whitespaces. + sValue = sValue.Trim(); + if (TryConvertToPoolBlockingPeriod(sValue, out result)) + { + return result; + } + + // string values must be valid + throw ADP.InvalidConnectionOptionValue(keyword); + } + else + { + // the value is not string, try other options + PoolBlockingPeriod eValue; + + if (value is PoolBlockingPeriod period) + { + // quick path for the most common case + eValue = period; + } + else if (value.GetType().IsEnum) + { + // explicitly block scenarios in which user tries to use wrong enum types, like: + // builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process; + // workaround: explicitly cast non-PoolBlockingPeriod enums to int + throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null); + } + else + { + try + { + // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest + eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value); + } + catch (ArgumentException e) + { + // to be consistent with the messages we send in case of wrong type usage, replace + // the error with our exception, and keep the original one as inner one for troubleshooting + throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e); + } + } + + // ensure value is in valid range + if (IsValidPoolBlockingPeriodValue(eValue)) + { + return eValue; + } + else + { + throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue); + } + } + } + } +} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs index 5b0f33c261..245ea3e45f 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionString.cs @@ -579,22 +579,22 @@ internal SqlConnectionString(string connectionString) : base(connectionString, G if (Authentication == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity && _hasPasswordKeyword) { - throw SQL.NonInteractiveWithPassword(DbConnectionStringBuilderUtil.ActiveDirectoryManagedIdentityString); + throw SQL.NonInteractiveWithPassword(DbConnectionStringUtilities.ActiveDirectoryManagedIdentityString); } if (Authentication == SqlAuthenticationMethod.ActiveDirectoryMSI && _hasPasswordKeyword) { - throw SQL.NonInteractiveWithPassword(DbConnectionStringBuilderUtil.ActiveDirectoryMSIString); + throw SQL.NonInteractiveWithPassword(DbConnectionStringUtilities.ActiveDirectoryMSIString); } if (Authentication == SqlAuthenticationMethod.ActiveDirectoryDefault && _hasPasswordKeyword) { - throw SQL.NonInteractiveWithPassword(DbConnectionStringBuilderUtil.ActiveDirectoryDefaultString); + throw SQL.NonInteractiveWithPassword(DbConnectionStringUtilities.ActiveDirectoryDefaultString); } if (Authentication == SqlAuthenticationMethod.ActiveDirectoryWorkloadIdentity && _hasPasswordKeyword) { - throw SQL.NonInteractiveWithPassword(DbConnectionStringBuilderUtil.ActiveDirectoryWorkloadIdentityString); + throw SQL.NonInteractiveWithPassword(DbConnectionStringUtilities.ActiveDirectoryWorkloadIdentityString); } } @@ -945,7 +945,7 @@ internal ApplicationIntent ConvertValueToApplicationIntent() // wrap Format and Overflow exceptions with Argument one, to be consistent with rest of the keyword types (like int and bool) try { - return DbConnectionStringBuilderUtil.ConvertToApplicationIntent(KEY.ApplicationIntent, value); + return DbConnectionStringUtilities.ConvertToApplicationIntent(KEY.ApplicationIntent, value); } catch (FormatException e) { @@ -977,7 +977,7 @@ internal SqlAuthenticationMethod ConvertValueToAuthenticationType() try { - return DbConnectionStringBuilderUtil.ConvertToAuthenticationType(KEY.Authentication, value); + return DbConnectionStringUtilities.ConvertToAuthenticationType(KEY.Authentication, value); } catch (FormatException e) { @@ -1002,7 +1002,7 @@ internal SqlConnectionColumnEncryptionSetting ConvertValueToColumnEncryptionSett try { - return DbConnectionStringBuilderUtil.ConvertToColumnEncryptionSetting(KEY.ColumnEncryptionSetting, value); + return DbConnectionStringUtilities.ConvertToColumnEncryptionSetting(KEY.ColumnEncryptionSetting, value); } catch (FormatException e) { @@ -1027,7 +1027,7 @@ internal SqlConnectionAttestationProtocol ConvertValueToAttestationProtocol() try { - return DbConnectionStringBuilderUtil.ConvertToAttestationProtocol(KEY.AttestationProtocol, value); + return AttestationProtocolUtilities.ConvertToAttestationProtocol(KEY.AttestationProtocol, value); } catch (FormatException e) { @@ -1052,7 +1052,7 @@ internal SqlConnectionIPAddressPreference ConvertValueToIPAddressPreference() try { - return DbConnectionStringBuilderUtil.ConvertToIPAddressPreference(KEY.IPAddressPreference, value); + return IpAddressPreferenceUtilities.ConvertToIPAddressPreference(KEY.IPAddressPreference, value); } catch (FormatException e) { @@ -1073,7 +1073,7 @@ internal PoolBlockingPeriod ConvertValueToPoolBlockingPeriod() try { - return DbConnectionStringBuilderUtil.ConvertToPoolBlockingPeriod(KEY.PoolBlockingPeriod, value); + return PoolBlockingUtilities.ConvertToPoolBlockingPeriod(KEY.PoolBlockingPeriod, value); } catch (Exception e) when (e is FormatException || e is OverflowException) { @@ -1090,7 +1090,7 @@ internal SqlConnectionEncryptOption ConvertValueToSqlConnectionEncrypt() try { - return DbConnectionStringBuilderUtil.ConvertToSqlConnectionEncryptOption(KEY.Encrypt, value); + return AttestationProtocolUtilities.ConvertToSqlConnectionEncryptOption(KEY.Encrypt, value); } catch (FormatException e) { diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs index 2bc6e1e43b..c86aeccb3c 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs @@ -275,34 +275,35 @@ private static Dictionary CreateKeywordsDictionary() Debug.Assert((KeywordsCount + SqlConnectionString.SynonymCount) == pairs.Count, "initial expected size is incorrect"); return pairs; } + + // @TODO These methods are completely unnecessary. - private static bool ConvertToBoolean(object value) => DbConnectionStringBuilderUtil.ConvertToBoolean(value); + private static bool ConvertToBoolean(object value) => DbConnectionStringUtilities.ConvertToBoolean(value); - private static int ConvertToInt32(object value) => DbConnectionStringBuilderUtil.ConvertToInt32(value); + private static int ConvertToInt32(object value) => DbConnectionStringUtilities.ConvertToInt32(value); - private static bool ConvertToIntegratedSecurity(object value) => DbConnectionStringBuilderUtil.ConvertToIntegratedSecurity(value); + private static bool ConvertToIntegratedSecurity(object value) => DbConnectionStringUtilities.ConvertToIntegratedSecurity(value); - private static SqlAuthenticationMethod ConvertToAuthenticationType(string keyword, object value) => DbConnectionStringBuilderUtil.ConvertToAuthenticationType(keyword, value); + private static SqlAuthenticationMethod ConvertToAuthenticationType(string keyword, object value) => DbConnectionStringUtilities.ConvertToAuthenticationType(keyword, value); - private static string ConvertToString(object value) => DbConnectionStringBuilderUtil.ConvertToString(value); + private static string ConvertToString(object value) => DbConnectionStringUtilities.ConvertToString(value); - private static ApplicationIntent ConvertToApplicationIntent(string keyword, object value) => DbConnectionStringBuilderUtil.ConvertToApplicationIntent(keyword, value); + private static ApplicationIntent ConvertToApplicationIntent(string keyword, object value) => DbConnectionStringUtilities.ConvertToApplicationIntent(keyword, value); private static SqlConnectionColumnEncryptionSetting ConvertToColumnEncryptionSetting(string keyword, object value) - => DbConnectionStringBuilderUtil.ConvertToColumnEncryptionSetting(keyword, value); + => DbConnectionStringUtilities.ConvertToColumnEncryptionSetting(keyword, value); private static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(string keyword, object value) - => DbConnectionStringBuilderUtil.ConvertToAttestationProtocol(keyword, value); + => AttestationProtocolUtilities.ConvertToAttestationProtocol(keyword, value); private static SqlConnectionEncryptOption ConvertToSqlConnectionEncryptOption(string keyword, object value) - => DbConnectionStringBuilderUtil.ConvertToSqlConnectionEncryptOption(keyword, value); - + => AttestationProtocolUtilities.ConvertToSqlConnectionEncryptOption(keyword, value); private static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(string keyword, object value) - => DbConnectionStringBuilderUtil.ConvertToIPAddressPreference(keyword, value); + => IpAddressPreferenceUtilities.ConvertToIPAddressPreference(keyword, value); private static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value) - => DbConnectionStringBuilderUtil.ConvertToPoolBlockingPeriod(keyword, value); + => PoolBlockingUtilities.ConvertToPoolBlockingPeriod(keyword, value); private object GetAt(Keywords index) { @@ -560,6 +561,8 @@ private void Reset(Keywords index) } } + // @TODO: These methods can be inlined with the property setters. + private void SetValue(string keyword, bool value) => base[keyword] = value.ToString(); private void SetValue(string keyword, int value) => base[keyword] = value.ToString((System.IFormatProvider)null); @@ -572,20 +575,20 @@ private void SetValue(string keyword, string value) private void SetApplicationIntentValue(ApplicationIntent value) { - Debug.Assert(DbConnectionStringBuilderUtil.IsValidApplicationIntentValue(value), "invalid value for ApplicationIntent"); - base[DbConnectionStringKeywords.ApplicationIntent] = DbConnectionStringBuilderUtil.ApplicationIntentToString(value); + Debug.Assert(DbConnectionStringUtilities.IsValidApplicationIntentValue(value), "invalid value for ApplicationIntent"); + base[DbConnectionStringKeywords.ApplicationIntent] = DbConnectionStringUtilities.ApplicationIntentToString(value); } private void SetColumnEncryptionSettingValue(SqlConnectionColumnEncryptionSetting value) { - Debug.Assert(DbConnectionStringBuilderUtil.IsValidColumnEncryptionSetting(value), "Invalid value for SqlConnectionColumnEncryptionSetting"); - base[DbConnectionStringKeywords.ColumnEncryptionSetting] = DbConnectionStringBuilderUtil.ColumnEncryptionSettingToString(value); + Debug.Assert(DbConnectionStringUtilities.IsValidColumnEncryptionSetting(value), "Invalid value for SqlConnectionColumnEncryptionSetting"); + base[DbConnectionStringKeywords.ColumnEncryptionSetting] = DbConnectionStringUtilities.ColumnEncryptionSettingToString(value); } private void SetAttestationProtocolValue(SqlConnectionAttestationProtocol value) { - Debug.Assert(DbConnectionStringBuilderUtil.IsValidAttestationProtocol(value), "Invalid value for SqlConnectionAttestationProtocol"); - base[DbConnectionStringKeywords.AttestationProtocol] = DbConnectionStringBuilderUtil.AttestationProtocolToString(value); + Debug.Assert(AttestationProtocolUtilities.IsValidAttestationProtocol(value), "Invalid value for SqlConnectionAttestationProtocol"); + base[DbConnectionStringKeywords.AttestationProtocol] = AttestationProtocolUtilities.AttestationProtocolToString(value); } private void SetSqlConnectionEncryptionValue(SqlConnectionEncryptOption value) @@ -595,20 +598,20 @@ private void SetSqlConnectionEncryptionValue(SqlConnectionEncryptOption value) private void SetIPAddressPreferenceValue(SqlConnectionIPAddressPreference value) { - Debug.Assert(DbConnectionStringBuilderUtil.IsValidIPAddressPreference(value), "Invalid value for SqlConnectionIPAddressPreference"); - base[DbConnectionStringKeywords.IPAddressPreference] = DbConnectionStringBuilderUtil.IPAddressPreferenceToString(value); + Debug.Assert(IpAddressPreferenceUtilities.IsValidIPAddressPreference(value), "Invalid value for SqlConnectionIPAddressPreference"); + base[DbConnectionStringKeywords.IPAddressPreference] = IpAddressPreferenceUtilities.IPAddressPreferenceToString(value); } private void SetAuthenticationValue(SqlAuthenticationMethod value) { - Debug.Assert(DbConnectionStringBuilderUtil.IsValidAuthenticationTypeValue(value), "Invalid value for AuthenticationType"); - base[DbConnectionStringKeywords.Authentication] = DbConnectionStringBuilderUtil.AuthenticationTypeToString(value); + Debug.Assert(DbConnectionStringUtilities.IsValidAuthenticationTypeValue(value), "Invalid value for AuthenticationType"); + base[DbConnectionStringKeywords.Authentication] = DbConnectionStringUtilities.AuthenticationTypeToString(value); } private void SetPoolBlockingPeriodValue(PoolBlockingPeriod value) { - Debug.Assert(DbConnectionStringBuilderUtil.IsValidPoolBlockingPeriodValue(value), "Invalid value for PoolBlockingPeriod"); - base[DbConnectionStringKeywords.PoolBlockingPeriod] = DbConnectionStringBuilderUtil.PoolBlockingPeriodToString(value); + Debug.Assert(PoolBlockingUtilities.IsValidPoolBlockingPeriodValue(value), "Invalid value for PoolBlockingPeriod"); + base[DbConnectionStringKeywords.PoolBlockingPeriod] = PoolBlockingUtilities.PoolBlockingPeriodToString(value); } private Exception UnsupportedKeyword(string keyword) @@ -1092,7 +1095,7 @@ public ApplicationIntent ApplicationIntent get => _applicationIntent; set { - if (!DbConnectionStringBuilderUtil.IsValidApplicationIntentValue(value)) + if (!DbConnectionStringUtilities.IsValidApplicationIntentValue(value)) { throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)value); } @@ -1275,7 +1278,7 @@ public SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting get => _columnEncryptionSetting; set { - if (!DbConnectionStringBuilderUtil.IsValidColumnEncryptionSetting(value)) + if (!DbConnectionStringUtilities.IsValidColumnEncryptionSetting(value)) { throw ADP.InvalidEnumerationValue(typeof(SqlConnectionColumnEncryptionSetting), (int)value); } @@ -1310,7 +1313,7 @@ public SqlConnectionAttestationProtocol AttestationProtocol get => _attestationProtocol; set { - if (!DbConnectionStringBuilderUtil.IsValidAttestationProtocol(value)) + if (!AttestationProtocolUtilities.IsValidAttestationProtocol(value)) { throw ADP.InvalidEnumerationValue(typeof(SqlConnectionAttestationProtocol), (int)value); } @@ -1330,7 +1333,7 @@ public SqlConnectionIPAddressPreference IPAddressPreference get => _ipAddressPreference; set { - if (!DbConnectionStringBuilderUtil.IsValidIPAddressPreference(value)) + if (!IpAddressPreferenceUtilities.IsValidIPAddressPreference(value)) { throw ADP.InvalidEnumerationValue(typeof(SqlConnectionIPAddressPreference), (int)value); } @@ -1444,7 +1447,7 @@ public SqlAuthenticationMethod Authentication get => _authentication; set { - if (!DbConnectionStringBuilderUtil.IsValidAuthenticationTypeValue(value)) + if (!DbConnectionStringUtilities.IsValidAuthenticationTypeValue(value)) { throw ADP.InvalidEnumerationValue(typeof(SqlAuthenticationMethod), (int)value); } @@ -1641,7 +1644,7 @@ public PoolBlockingPeriod PoolBlockingPeriod get => _poolBlockingPeriod; set { - if (!DbConnectionStringBuilderUtil.IsValidPoolBlockingPeriodValue(value)) + if (!PoolBlockingUtilities.IsValidPoolBlockingPeriodValue(value)) { throw ADP.InvalidEnumerationValue(typeof(PoolBlockingPeriod), (int)value); } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUtil.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUtil.cs index c398110849..835f1ae640 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUtil.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUtil.cs @@ -492,7 +492,7 @@ static internal Exception UserInstanceFailoverNotCompatible() } static internal Exception CredentialsNotProvided(SqlAuthenticationMethod auth) { - return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_CredentialsNotProvided, DbConnectionStringBuilderUtil.AuthenticationTypeToString(auth))); + return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_CredentialsNotProvided, DbConnectionStringUtilities.AuthenticationTypeToString(auth))); } static internal Exception InvalidCertAuth() {