diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionIPAddressPreference.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionIPAddressPreference.xml
new file mode 100644
index 0000000000..e713cb776b
--- /dev/null
+++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionIPAddressPreference.xml
@@ -0,0 +1,40 @@
+
+    
+        
+            
+                Specifies a value for IP address preference during a TCP connection.
+            
+            
+                
+            
+        
+        
+            
+                Specifies a value for IP address preference during a TCP connection.
+            
+            
+                
+            
+        
+        
+            Connects using IPv4 address(es) first. If the connection fails, try IPv6 address(es), if provided. This is the default value.
+            0
+        
+        
+            Connect using IPv6 address(es) first. If the connection fails, try IPv4 address(es), if available.
+            1
+        
+        
+            Connects with IP addresses in the order the underlying platform or operating system provides them.
+            2
+        
+    
+
diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml
index 46e9ee6877..619ea2d690 100644
--- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml
+++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml
@@ -346,6 +346,17 @@ False
             
             To set the value to null, use .
         
+        
+            Gets or sets the value of IP address preference.
+            Returns IP address preference.
+            
+                
+            
+        
         
             Gets or sets the enclave attestation Url to be used with enclave based Always Encrypted.
             The enclave attestation Url.
diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs
index e630a03acb..17bc6c59c4 100644
--- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs
@@ -398,6 +398,18 @@ public enum SqlConnectionAttestationProtocol
         HGS = 3
     }
 #endif
+    /// 
+    public enum SqlConnectionIPAddressPreference
+    {
+        /// 
+        IPv4First = 0,  // default
+
+        /// 
+        IPv6First = 1,
+
+        /// 
+        UsePlatformDefault = 2
+    }
     /// 
     public partial class SqlColumnEncryptionCertificateStoreProvider : Microsoft.Data.SqlClient.SqlColumnEncryptionKeyStoreProvider
     {
@@ -883,6 +895,10 @@ public SqlConnectionStringBuilder(string connectionString) { }
         [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
         public string EnclaveAttestationUrl { get { throw null; } set { } }
 #endif
+        /// 
+        [System.ComponentModel.DisplayNameAttribute("IP Address Preference")]
+        [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
+        public Microsoft.Data.SqlClient.SqlConnectionIPAddressPreference IPAddressPreference { get { throw null; } set { } }
         /// 
         [System.ComponentModel.DisplayNameAttribute("Encrypt")]
         [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs
index 8201ec41aa..20159ca382 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs
@@ -165,6 +165,7 @@ private unsafe struct SNI_CLIENT_CONSUMER_INFO
             public TransparentNetworkResolutionMode transparentNetworkResolution;
             public int totalTimeout;
             public bool isAzureSqlServerEndpoint;
+            public SqlConnectionIPAddressPreference ipAddressPreference;
             public SNI_DNSCache_Info DNSCacheInfo;
         }
 
@@ -275,6 +276,7 @@ private static extern uint SNIOpenWrapper(
             [In] SNIHandle pConn,
             out IntPtr ppConn,
             [MarshalAs(UnmanagedType.Bool)] bool fSync,
+            SqlConnectionIPAddressPreference ipPreference,
             [In] ref SNI_DNSCache_Info pDNSCachedInfo);
 
         [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
@@ -341,7 +343,7 @@ internal static uint SNIInitialize()
             return SNIInitialize(IntPtr.Zero);
         }
 
-        internal static unsafe uint SNIOpenMarsSession(ConsumerInfo consumerInfo, SNIHandle parent, ref IntPtr pConn, bool fSync, SQLDNSInfo cachedDNSInfo)
+        internal static unsafe uint SNIOpenMarsSession(ConsumerInfo consumerInfo, SNIHandle parent, ref IntPtr pConn, bool fSync, SqlConnectionIPAddressPreference ipPreference, SQLDNSInfo cachedDNSInfo)
         {
             // initialize consumer info for MARS
             Sni_Consumer_Info native_consumerInfo = new Sni_Consumer_Info();
@@ -353,10 +355,11 @@ internal static unsafe uint SNIOpenMarsSession(ConsumerInfo consumerInfo, SNIHan
             native_cachedDNSInfo.wszCachedTcpIPv6 = cachedDNSInfo?.AddrIPv6;
             native_cachedDNSInfo.wszCachedTcpPort = cachedDNSInfo?.Port;
 
-            return SNIOpenWrapper(ref native_consumerInfo, "session:", parent, out pConn, fSync, ref native_cachedDNSInfo);
+            return SNIOpenWrapper(ref native_consumerInfo, "session:", parent, out pConn, fSync, ipPreference, ref native_cachedDNSInfo);
         }
 
-        internal static unsafe uint SNIOpenSyncEx(ConsumerInfo consumerInfo, string constring, ref IntPtr pConn, byte[] spnBuffer, byte[] instanceName, bool fOverrideCache, bool fSync, int timeout, bool fParallel, SQLDNSInfo cachedDNSInfo)
+        internal static unsafe uint SNIOpenSyncEx(ConsumerInfo consumerInfo, string constring, ref IntPtr pConn, byte[] spnBuffer, byte[] instanceName, bool fOverrideCache, 
+                                    bool fSync, int timeout, bool fParallel, SqlConnectionIPAddressPreference ipPreference, SQLDNSInfo cachedDNSInfo)
         {
             fixed (byte* pin_instanceName = &instanceName[0])
             {
@@ -379,6 +382,7 @@ internal static unsafe uint SNIOpenSyncEx(ConsumerInfo consumerInfo, string cons
                 clientConsumerInfo.totalTimeout = SniOpenTimeOut;
                 clientConsumerInfo.isAzureSqlServerEndpoint = ADP.IsAzureSqlServerEndpoint(constring);
 
+                clientConsumerInfo.ipAddressPreference = ipPreference;
                 clientConsumerInfo.DNSCacheInfo.wszCachedFQDN = cachedDNSInfo?.FQDN;
                 clientConsumerInfo.DNSCacheInfo.wszCachedTcpIPv4 = cachedDNSInfo?.AddrIPv4;
                 clientConsumerInfo.DNSCacheInfo.wszCachedTcpIPv6 = cachedDNSInfo?.AddrIPv6;
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionStringCommon.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionStringCommon.cs
index eb23fcdfef..3c22c4ecd8 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionStringCommon.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionStringCommon.cs
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.Globalization;
 using System.Reflection;
@@ -400,6 +401,110 @@ internal static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(st
 
         #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
+
         internal static bool IsValidApplicationIntentValue(ApplicationIntent value)
         {
             Debug.Assert(Enum.GetNames(typeof(ApplicationIntent)).Length == 2, "ApplicationIntent enum has changed, update needed");
@@ -728,6 +833,7 @@ internal static partial class DbConnectionStringDefaults
         internal const SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
         internal const string EnclaveAttestationUrl = _emptyString;
         internal const SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified;
+        internal const SqlConnectionIPAddressPreference IPAddressPreference = SqlConnectionIPAddressPreference.IPv4First;
     }
 
 
@@ -765,6 +871,7 @@ internal static partial class DbConnectionStringKeywords
         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";
 
         // common keywords (OleDb, OracleClient, SqlClient)
         internal const string DataSource = "Data Source";
@@ -793,6 +900,9 @@ internal static class DbConnectionStringSynonyms
         //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";
 
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs
index e05b7498f8..5823e7f44c 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs
@@ -254,10 +254,12 @@ internal uint WritePacket(SNIHandle handle, SNIPacket packet, bool sync)
         /// Asynchronous connection
         /// Attempt parallel connects
         /// 
+        /// IP address preference
         /// Used for DNS Cache
-        /// Used for DNS Cache
+        /// Used for DNS Cache       
         /// SNI handle
-        internal SNIHandle CreateConnectionHandle(string fullServerName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, bool flushCache, bool async, bool parallel, bool isIntegratedSecurity, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
+        internal SNIHandle CreateConnectionHandle(string fullServerName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, 
+                                        bool flushCache, bool async, bool parallel, bool isIntegratedSecurity, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
         {
             instanceName = new byte[1];
 
@@ -284,7 +286,7 @@ internal SNIHandle CreateConnectionHandle(string fullServerName, bool ignoreSniO
                 case DataSource.Protocol.Admin:
                 case DataSource.Protocol.None: // default to using tcp if no protocol is provided
                 case DataSource.Protocol.TCP:
-                    sniHandle = CreateTcpHandle(details, timerExpire, parallel, cachedFQDN, ref pendingDNSInfo);
+                    sniHandle = CreateTcpHandle(details, timerExpire, parallel, ipPreference, cachedFQDN, ref pendingDNSInfo);
                     break;
                 case DataSource.Protocol.NP:
                     sniHandle = CreateNpHandle(details, timerExpire, parallel);
@@ -374,10 +376,11 @@ private static byte[][] GetSqlServerSPNs(string hostNameOrAddress, string portOr
         /// Data source
         /// Timer expiration
         /// Should MultiSubnetFailover be used
+        /// IP address preference
         /// Key for DNS Cache
-        /// Used for DNS Cache
+        /// Used for DNS Cache        
         /// SNITCPHandle
-        private SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, bool parallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
+        private SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, bool parallel, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
         {
             // TCP Format:
             // tcp:\
@@ -415,7 +418,7 @@ private SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, bool
                 port = isAdminConnection ? DefaultSqlServerDacPort : DefaultSqlServerPort;
             }
 
-            return new SNITCPHandle(hostName, port, timerExpire, parallel, cachedFQDN, ref pendingDNSInfo);
+            return new SNITCPHandle(hostName, port, timerExpire, parallel, ipPreference, cachedFQDN, ref pendingDNSInfo);
         }
 
 
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
index 4ca0631c51..d2a8341c0f 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
@@ -116,9 +116,10 @@ public override int ProtocolVersion
         /// TCP port number
         /// Connection timer expiration
         /// Parallel executions
+        /// IP address preference
         /// Key for DNS Cache
-        /// Used for DNS Cache
-        public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
+        /// Used for DNS Cache        
+        public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
         {
             long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);
             SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "Connection Id {0}, Setting server name = {1}", args0: _connectionId, args1: serverName);
@@ -147,8 +148,8 @@ public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel
 
                     SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "Connection Id {0}, Connecting to serverName {1} and port {2}", args0: _connectionId, args1: serverName, args2: port);
                     // We will always first try to connect with serverName as before and let the DNS server to resolve the serverName.
-                    // If the DSN resolution fails, we will try with IPs in the DNS cache if existed. We try with IPv4 first and followed by IPv6 if
-                    // IPv4 fails. The exceptions will be throw to upper level and be handled as before.
+                    // If the DSN resolution fails, we will try with IPs in the DNS cache if existed. We try with cached IPs based on IPAddressPreference.
+                    // The exceptions will be throw to upper level and be handled as before.
                     try
                     {
                         if (parallel)
@@ -157,7 +158,7 @@ public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel
                         }
                         else
                         {
-                            _socket = Connect(serverName, port, ts, isInfiniteTimeOut, cachedFQDN, ref pendingDNSInfo);
+                            _socket = Connect(serverName, port, ts, isInfiniteTimeOut, ipPreference, cachedFQDN, ref pendingDNSInfo);
                         }
                     }
                     catch (Exception ex)
@@ -175,15 +176,26 @@ public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel
                                 int portRetry = string.IsNullOrEmpty(cachedDNSInfo.Port) ? port : int.Parse(cachedDNSInfo.Port);
                                 SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "Connection Id {0}, Retrying with cached DNS IP Address {1} and port {2}", args0: _connectionId, args1: cachedDNSInfo.AddrIPv4, args2: cachedDNSInfo.Port);
 
+                                string firstCachedIP;
+                                string secondCachedIP;
+
+                                if (SqlConnectionIPAddressPreference.IPv6First == ipPreference) {
+                                    firstCachedIP = cachedDNSInfo.AddrIPv6;
+                                    secondCachedIP = cachedDNSInfo.AddrIPv4;
+                                } else {
+                                    firstCachedIP = cachedDNSInfo.AddrIPv4;
+                                    secondCachedIP = cachedDNSInfo.AddrIPv6;
+                                }
+
                                 try
                                 {
                                     if (parallel)
                                     {
-                                        _socket = TryConnectParallel(cachedDNSInfo.AddrIPv4, portRetry, ts, isInfiniteTimeOut, ref reportError, cachedFQDN, ref pendingDNSInfo);
+                                        _socket = TryConnectParallel(firstCachedIP, portRetry, ts, isInfiniteTimeOut, ref reportError, cachedFQDN, ref pendingDNSInfo);
                                     }
                                     else
                                     {
-                                        _socket = Connect(cachedDNSInfo.AddrIPv4, portRetry, ts, isInfiniteTimeOut, cachedFQDN, ref pendingDNSInfo);
+                                        _socket = Connect(firstCachedIP, portRetry, ts, isInfiniteTimeOut, ipPreference, cachedFQDN, ref pendingDNSInfo);
                                     }
                                 }
                                 catch (Exception exRetry)
@@ -194,11 +206,11 @@ public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel
                                         SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "Connection Id {0}, Retrying exception {1}", args0: _connectionId, args1: exRetry?.Message);
                                         if (parallel)
                                         {
-                                            _socket = TryConnectParallel(cachedDNSInfo.AddrIPv6, portRetry, ts, isInfiniteTimeOut, ref reportError, cachedFQDN, ref pendingDNSInfo);
+                                            _socket = TryConnectParallel(secondCachedIP, portRetry, ts, isInfiniteTimeOut, ref reportError, cachedFQDN, ref pendingDNSInfo);
                                         }
                                         else
                                         {
-                                            _socket = Connect(cachedDNSInfo.AddrIPv6, portRetry, ts, isInfiniteTimeOut, cachedFQDN, ref pendingDNSInfo);
+                                            _socket = Connect(secondCachedIP, portRetry, ts, isInfiniteTimeOut, ipPreference, cachedFQDN, ref pendingDNSInfo);
                                         }
                                     }
                                     else
@@ -320,42 +332,37 @@ private Socket TryConnectParallel(string hostName, int port, TimeSpan ts, bool i
         // Connect to server with hostName and port.
         // The IP information will be collected temporarily as the pendingDNSInfo but is not stored in the DNS cache at this point.
         // Only write to the DNS cache when we receive IsSupported flag as true in the Feature Ext Ack from server.
-        private static Socket Connect(string serverName, int port, TimeSpan timeout, bool isInfiniteTimeout, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
+        private static Socket Connect(string serverName, int port, TimeSpan timeout, bool isInfiniteTimeout, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
         {
+            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "IP preference : {0}", Enum.GetName(typeof(SqlConnectionIPAddressPreference), ipPreference));
+
             IPAddress[] ipAddresses = Dns.GetHostAddresses(serverName);
 
             string IPv4String = null;
-            string IPv6String = null;
-
+            string IPv6String = null;         
+            
             // Returning null socket is handled by the caller function.
-            if(ipAddresses == null || ipAddresses.Length == 0)
+            if (ipAddresses == null || ipAddresses.Length == 0)
             {
                 return null;
             }
 
             Socket[] sockets = new Socket[ipAddresses.Length];
-            AddressFamily[] preferedIPFamilies = new AddressFamily[] { AddressFamily.InterNetwork, AddressFamily.InterNetworkV6 };
-
-            CancellationTokenSource cts = null;
+            AddressFamily[] preferedIPFamilies = new AddressFamily[2];
 
-            void Cancel()
+            if (ipPreference == SqlConnectionIPAddressPreference.IPv4First)
             {
-                for (int i = 0; i < sockets.Length; ++i)
-                {
-                    try
-                    {
-                        if (sockets[i] != null && !sockets[i].Connected)
-                        {
-                            sockets[i].Dispose();
-                            sockets[i] = null;
-                        }
-                    }
-                    catch (Exception e)
-                    {
-                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "THIS EXCEPTION IS BEING SWALLOWED: {0}", args0: e?.Message);
-                    }
-                }
+                preferedIPFamilies[0] = AddressFamily.InterNetwork;
+                preferedIPFamilies[1] = AddressFamily.InterNetworkV6;
             }
+            else if (ipPreference == SqlConnectionIPAddressPreference.IPv6First)
+            {
+                preferedIPFamilies[0] = AddressFamily.InterNetworkV6;
+                preferedIPFamilies[1] = AddressFamily.InterNetwork;
+            }
+            // else -> UsePlatformDefault
+
+            CancellationTokenSource cts = null;
 
             if (!isInfiniteTimeout)
             {
@@ -366,32 +373,39 @@ void Cancel()
             Socket availableSocket = null;
             try
             {
-                int n = 0; // Socket index
-
                 // We go through the IP list twice.
                 // In the first traversal, we only try to connect with the preferedIPFamilies[0].
                 // In the second traversal, we only try to connect with the preferedIPFamilies[1].
+                // For UsePlatformDefault preference, we do traversal once.
                 for (int i = 0; i < preferedIPFamilies.Length; ++i)
                 {
-                    foreach (IPAddress ipAddress in ipAddresses)
+                    for (int n = 0; n < ipAddresses.Length; n++)
                     {
+                        IPAddress ipAddress = ipAddresses[n];
                         try
                         {
-                            if (ipAddress != null && ipAddress.AddressFamily == preferedIPFamilies[i])
+                            if (ipAddress != null)
                             {
+                                if (ipAddress.AddressFamily != preferedIPFamilies[i] && ipPreference != SqlConnectionIPAddressPreference.UsePlatformDefault)
+                                {
+                                    continue;
+                                }
+
                                 sockets[n] = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
 
                                 // enable keep-alive on socket
                                 SetKeepAliveValues(ref sockets[n]);
 
-                                SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "Connecting to IP address {0} and port {1}", args0: ipAddress, args1: port);
+                                SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "Connecting to IP address {0} and port {1} using {2} address family.",
+                                                                          args0: ipAddress,
+                                                                          args1: port,
+                                                                          args2: ipAddress.AddressFamily);
                                 sockets[n].Connect(ipAddress, port);
-                                if (sockets[n] != null) // sockets[i] can be null if cancel callback is executed during connect()
+                                if (sockets[n] != null) // sockets[n] can be null if cancel callback is executed during connect()
                                 {
                                     if (sockets[n].Connected)
                                     {
                                         availableSocket = sockets[n];
-
                                         if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
                                         {
                                             IPv4String = ipAddress.ToString();
@@ -409,20 +423,21 @@ void Cancel()
                                         sockets[n] = null;
                                     }
                                 }
-                                n++;
                             }
                         }
                         catch (Exception e)
                         {
                             SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "THIS EXCEPTION IS BEING SWALLOWED: {0}", args0: e?.Message);
+                            SqlClientEventSource.Log.TryAdvancedTraceEvent($"{s_className}.{System.Reflection.MethodBase.GetCurrentMethod().Name}{EventType.ERR}THIS EXCEPTION IS BEING SWALLOWED: {e}");
                         }
                     }
 
-                    // If we have already got an valid Socket, we won't do the second traversal.
-                    if (availableSocket != null) 
+                    // If we have already got a valid Socket, or the platform default was prefered
+                    // we won't do the second traversal.
+                    if (availableSocket != null || ipPreference == SqlConnectionIPAddressPreference.UsePlatformDefault) 
                     {
                         break;
-                    }                    
+                    }
                 }
             }
             finally
@@ -437,6 +452,25 @@ void Cancel()
             }
 
             return availableSocket;
+
+            void Cancel()
+            {
+                for (int i = 0; i < sockets.Length; ++i)
+                {
+                    try
+                    {
+                        if (sockets[i] != null && !sockets[i].Connected)
+                        {
+                            sockets[i].Dispose();
+                            sockets[i] = null;
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "THIS EXCEPTION IS BEING SWALLOWED: {0}", args0: e?.Message);
+                    }
+                }
+            }
         }
 
         private static Task ParallelConnectAsync(IPAddress[] serverAddresses, int port)
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 7cdd3b56d5..d89f841b48 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
@@ -391,6 +391,14 @@ internal SqlConnectionAttestationProtocol AttestationProtocol
             }
         }
 
+        /// 
+        /// Get IP address preference
+        /// 
+        internal SqlConnectionIPAddressPreference iPAddressPreference
+        {
+            get => ((SqlConnectionString)ConnectionOptions).IPAddressPreference;
+        }
+
         // This method will be called once connection string is set or changed.
         private void CacheConnectionStringProperties()
         {
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionString.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionString.cs
index aa9023139c..d2d2cf7891 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionString.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionString.cs
@@ -53,6 +53,7 @@ internal static partial class DEFAULT
             internal const SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
             internal const string EnclaveAttestationUrl = _emptyString;
             internal static readonly SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified;
+            internal static readonly SqlConnectionIPAddressPreference s_IPAddressPreference = SqlConnectionIPAddressPreference.IPv4First;
         }
 
         // SqlConnection ConnectionString Options
@@ -69,6 +70,7 @@ internal static class KEY
             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 Command_Timeout = "command timeout";
             internal const string Connect_Timeout = "connect timeout";
@@ -106,6 +108,8 @@ internal static class KEY
         // Constant for the number of duplicate options in the connection string
         private static class SYNONYM
         {
+            // ip address preference
+            internal const string IPADDRESSPREFERENCE = "ipaddresspreference";
             //application intent
             internal const string APPLICATIONINTENT = "applicationintent";
             // application name
@@ -160,9 +164,9 @@ private static class SYNONYM
         }
 
 #if NETCOREAPP
-        internal const int SynonymCount = 25;
+        internal const int SynonymCount = 26;
 #else
-        internal const int SynonymCount = 24;
+        internal const int SynonymCount = 25;
 #endif
         internal const int DeprecatedSynonymCount = 3;
 
@@ -213,6 +217,7 @@ internal static class TRANSACTIONBINDING
         private readonly SqlConnectionColumnEncryptionSetting _columnEncryptionSetting;
         private readonly string _enclaveAttestationUrl;
         private readonly SqlConnectionAttestationProtocol _attestationProtocol;
+        private readonly SqlConnectionIPAddressPreference _ipAddressPreference;
 
         private readonly int _commandTimeout;
         private readonly int _connectTimeout;
@@ -293,6 +298,7 @@ internal SqlConnectionString(string connectionString) : base(connectionString, G
             _columnEncryptionSetting = ConvertValueToColumnEncryptionSetting();
             _enclaveAttestationUrl = ConvertValueToString(KEY.EnclaveAttestationUrl, DEFAULT.EnclaveAttestationUrl);
             _attestationProtocol = ConvertValueToAttestationProtocol();
+            _ipAddressPreference = ConvertValueToIPAddressPreference();
 
             // Temporary string - this value is stored internally as an enum.
             string typeSystemVersionString = ConvertValueToString(KEY.Type_System_Version, null);
@@ -559,6 +565,7 @@ internal SqlConnectionString(SqlConnectionString connectionOptions, string dataS
         internal SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting { get { return _columnEncryptionSetting; } }
         internal string EnclaveAttestationUrl { get { return _enclaveAttestationUrl; } }
         internal SqlConnectionAttestationProtocol AttestationProtocol { get { return _attestationProtocol; } }
+        internal SqlConnectionIPAddressPreference IPAddressPreference => _ipAddressPreference;
         internal bool PersistSecurityInfo { get { return _persistSecurityInfo; } }
         internal bool Pooling { get { return _pooling; } }
         internal bool Replication { get { return _replication; } }
@@ -687,6 +694,7 @@ internal static Dictionary GetParseSynonyms()
                     { KEY.Connect_Retry_Count, KEY.Connect_Retry_Count },
                     { KEY.Connect_Retry_Interval, KEY.Connect_Retry_Interval },
                     { KEY.Authentication, KEY.Authentication },
+                    { KEY.IPAddressPreference, KEY.IPAddressPreference },
 
                     { SYNONYM.APP, KEY.Application_Name },
                     { SYNONYM.APPLICATIONINTENT, KEY.ApplicationIntent },
@@ -717,7 +725,8 @@ internal static Dictionary GetParseSynonyms()
                     { SYNONYM.TRUSTSERVERCERTIFICATE, KEY.TrustServerCertificate },
                     { SYNONYM.UID, KEY.User_ID },
                     { SYNONYM.User, KEY.User_ID },
-                    { SYNONYM.WSID, KEY.Workstation_Id }
+                    { SYNONYM.WSID, KEY.Workstation_Id },
+                    { SYNONYM.IPADDRESSPREFERENCE, KEY.IPAddressPreference }
                 };
                 Debug.Assert(synonyms.Count == count, "incorrect initial ParseSynonyms size");
                 Interlocked.CompareExchange(ref s_sqlClientSynonyms, synonyms, null);
@@ -898,5 +907,30 @@ internal SqlConnectionAttestationProtocol ConvertValueToAttestationProtocol()
                 throw ADP.InvalidConnectionOptionValue(KEY.AttestationProtocol, e);
             }
         }
+
+        /// 
+        /// Convert the value to SqlConnectionIPAddressPreference
+        /// 
+        /// 
+        internal SqlConnectionIPAddressPreference ConvertValueToIPAddressPreference()
+        {
+            if (!TryGetParsetableValue(KEY.IPAddressPreference, out string value))
+            {
+                return DEFAULT.s_IPAddressPreference;
+            }
+
+            try
+            {
+                return DbConnectionStringBuilderUtil.ConvertToIPAddressPreference(KEY.IPAddressPreference, value);
+            }
+            catch (FormatException e)
+            {
+                throw ADP.InvalidConnectionOptionValue(KEY.IPAddressPreference, e);
+            }
+            catch (OverflowException e)
+            {
+                throw ADP.InvalidConnectionOptionValue(KEY.IPAddressPreference, e);
+            }
+        }
     }
 }
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
index 0a7a06659a..9102b07a4a 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
@@ -59,6 +59,7 @@ private enum Keywords
             AttestationProtocol,
 
             CommandTimeout,
+            IPAddressPreference,
 
             // keep the count value last
             KeywordsCount
@@ -107,6 +108,7 @@ private enum Keywords
         private SqlConnectionColumnEncryptionSetting _columnEncryptionSetting = DbConnectionStringDefaults.ColumnEncryptionSetting;
         private string _enclaveAttestationUrl = DbConnectionStringDefaults.EnclaveAttestationUrl;
         private SqlConnectionAttestationProtocol _attestationProtocol = DbConnectionStringDefaults.AttestationProtocol;
+        private SqlConnectionIPAddressPreference _ipAddressPreference = DbConnectionStringDefaults.IPAddressPreference;
 
         private static string[] CreateValidKeywords()
         {
@@ -149,6 +151,7 @@ private static string[] CreateValidKeywords()
             validKeywords[(int)Keywords.ColumnEncryptionSetting] = DbConnectionStringKeywords.ColumnEncryptionSetting;
             validKeywords[(int)Keywords.EnclaveAttestationUrl] = DbConnectionStringKeywords.EnclaveAttestationUrl;
             validKeywords[(int)Keywords.AttestationProtocol] = DbConnectionStringKeywords.AttestationProtocol;
+            validKeywords[(int)Keywords.IPAddressPreference] = DbConnectionStringKeywords.IPAddressPreference;
             return validKeywords;
         }
 
@@ -193,7 +196,9 @@ private static Dictionary CreateKeywordsDictionary()
             hash.Add(DbConnectionStringKeywords.ColumnEncryptionSetting, Keywords.ColumnEncryptionSetting);
             hash.Add(DbConnectionStringKeywords.EnclaveAttestationUrl, Keywords.EnclaveAttestationUrl);
             hash.Add(DbConnectionStringKeywords.AttestationProtocol, Keywords.AttestationProtocol);
+            hash.Add(DbConnectionStringKeywords.IPAddressPreference, Keywords.IPAddressPreference);
 
+            hash.Add(DbConnectionStringSynonyms.IPADDRESSPREFERENCE, Keywords.IPAddressPreference);
             hash.Add(DbConnectionStringSynonyms.APP, Keywords.ApplicationName);
             hash.Add(DbConnectionStringSynonyms.APPLICATIONINTENT, Keywords.ApplicationIntent);
             hash.Add(DbConnectionStringSynonyms.EXTENDEDPROPERTIES, Keywords.AttachDBFilename);
@@ -326,6 +331,9 @@ public override object this[string keyword]
                         case Keywords.AttestationProtocol:
                             AttestationProtocol = ConvertToAttestationProtocol(keyword, value);
                             break;
+                        case Keywords.IPAddressPreference:
+                            IPAddressPreference = ConvertToIPAddressPreference(keyword, value);
+                            break;
 #if NETCOREAPP
                         case Keywords.PoolBlockingPeriod: PoolBlockingPeriod = ConvertToPoolBlockingPeriod(keyword, value); break;
 #endif
@@ -519,6 +527,22 @@ public SqlConnectionAttestationProtocol AttestationProtocol
             }
         }
 
+        /// 
+        public SqlConnectionIPAddressPreference IPAddressPreference
+        {
+            get => _ipAddressPreference;
+            set
+            {
+                if (!DbConnectionStringBuilderUtil.IsValidIPAddressPreference(value))
+                {
+                    throw ADP.InvalidEnumerationValue(typeof(SqlConnectionIPAddressPreference), (int)value);
+                }
+
+                SetIPAddressPreferenceValue(value);
+                _ipAddressPreference = value;
+            }
+        }
+
         /// 
         public bool TrustServerCertificate
         {
@@ -904,6 +928,14 @@ private static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(str
             return DbConnectionStringBuilderUtil.ConvertToAttestationProtocol(keyword, value);
         }
 
+        /// 
+        /// Convert to SqlConnectionIPAddressPreference
+        /// 
+        /// 
+        /// 
+        private static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(string keyword, object value)
+            => DbConnectionStringBuilderUtil.ConvertToIPAddressPreference(keyword, value);
+
         private object GetAt(Keywords index)
         {
             switch (index)
@@ -980,6 +1012,8 @@ private object GetAt(Keywords index)
                     return EnclaveAttestationUrl;
                 case Keywords.AttestationProtocol:
                     return AttestationProtocol;
+                case Keywords.IPAddressPreference:
+                    return IPAddressPreference;
                 default:
                     Debug.Fail("unexpected keyword");
                     throw UnsupportedKeyword(s_validKeywords[(int)index]);
@@ -1127,6 +1161,9 @@ private void Reset(Keywords index)
                 case Keywords.AttestationProtocol:
                     _attestationProtocol = DbConnectionStringDefaults.AttestationProtocol;
                     break;
+                case Keywords.IPAddressPreference:
+                    _ipAddressPreference = DbConnectionStringDefaults.IPAddressPreference;
+                    break;
                 default:
                     Debug.Fail("unexpected keyword");
                     throw UnsupportedKeyword(s_validKeywords[(int)index]);
@@ -1163,6 +1200,12 @@ private void SetAttestationProtocolValue(SqlConnectionAttestationProtocol value)
             base[DbConnectionStringKeywords.AttestationProtocol] = DbConnectionStringBuilderUtil.AttestationProtocolToString(value);
         }
 
+        private void SetIPAddressPreferenceValue(SqlConnectionIPAddressPreference value)
+        {
+            Debug.Assert(DbConnectionStringBuilderUtil.IsValidIPAddressPreference(value), "Invalid value for SqlConnectionIPAddressPreference");
+            base[DbConnectionStringKeywords.IPAddressPreference] = DbConnectionStringBuilderUtil.IPAddressPreferenceToString(value);
+        }
+
         private void SetAuthenticationValue(SqlAuthenticationMethod value)
         {
             Debug.Assert(DbConnectionStringBuilderUtil.IsValidAuthenticationTypeValue(value), "Invalid value for AuthenticationType");
@@ -1306,4 +1349,3 @@ public override StandardValuesCollection GetStandardValues(ITypeDescriptorContex
         }
     }
 }
-
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs
index 5dcda47e0f..3935ed01e4 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs
@@ -21,7 +21,7 @@
 
 namespace Microsoft.Data.SqlClient
 {
-    internal class SessionStateRecord
+    internal sealed class SessionStateRecord
     {
         internal bool _recoverable;
         internal uint _version;
@@ -29,7 +29,7 @@ internal class SessionStateRecord
         internal byte[] _data;
     }
 
-    internal class SessionData
+    internal sealed class SessionData
     {
         internal const int _maxNumberOfSessionStates = 256;
         internal uint _tdsVersion;
@@ -101,7 +101,7 @@ public void AssertUnrecoverableStateCountIsCorrect()
         }
     }
 
-    sealed internal class SqlInternalConnectionTds : SqlInternalConnection, IDisposable
+    internal sealed class SqlInternalConnectionTds : SqlInternalConnection, IDisposable
     {
         // CONNECTION AND STATE VARIABLES
         private readonly SqlConnectionPoolGroupProviderInfo _poolGroupProviderInfo; // will only be null when called for ChangePassword, or creating SSE User Instance
@@ -2481,12 +2481,9 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
 
         internal void OnFeatureExtAck(int featureId, byte[] data)
         {
-            if (RoutingInfo != null)
+            if (RoutingInfo != null && TdsEnums.FEATUREEXT_SQLDNSCACHING != featureId)
             {
-                if (TdsEnums.FEATUREEXT_SQLDNSCACHING != featureId)
-                {
-                    return;
-                }
+                return;
             }
 
             switch (featureId)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsEnums.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsEnums.cs
index 416ec86fd0..9099f5882c 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsEnums.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsEnums.cs
@@ -1077,6 +1077,19 @@ public enum SqlConnectionAttestationProtocol
         HGS = 3
     }
 
+    /// 
+    public enum SqlConnectionIPAddressPreference
+    {
+        /// 
+        IPv4First = 0,  // default
+
+        /// 
+        IPv6First = 1,
+
+        /// 
+        UsePlatformDefault = 2
+    }
+
     /// 
     public enum SqlConnectionColumnEncryptionSetting
     {
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs
index e0ebfdf669..9e26aa375f 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs
@@ -412,8 +412,8 @@ internal void Connect(
             _connHandler.pendingSQLDNSObject = null;
 
             // AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server
-            _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire,
-                        out instanceName, ref _sniSpnBuffer, false, true, fParallel, FQDNforDNSCahce, ref _connHandler.pendingSQLDNSObject, integratedSecurity || authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated);
+            _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, false, true, fParallel,
+                              _connHandler.ConnectionOptions.IPAddressPreference, FQDNforDNSCahce, ref _connHandler.pendingSQLDNSObject, integratedSecurity || authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated);
 
             if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status)
             {
@@ -477,7 +477,8 @@ internal void Connect(
                 // On Instance failure re-connect and flush SNI named instance cache.
                 _physicalStateObj.SniContext = SniContext.Snix_Connect;
 
-                _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, true, true, fParallel, FQDNforDNSCahce, ref _connHandler.pendingSQLDNSObject, integratedSecurity);
+                _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, true, true, fParallel, 
+                                                _connHandler.ConnectionOptions.IPAddressPreference, FQDNforDNSCahce, ref _connHandler.pendingSQLDNSObject, integratedSecurity);
 
                 if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status)
                 {
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.cs
index 921d72a385..62411969ff 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.cs
@@ -144,6 +144,7 @@ internal SNIHandle(
             bool flushCache,
             bool fSync,
             bool fParallel,
+            SqlConnectionIPAddressPreference ipPreference,
             SQLDNSInfo cachedDNSInfo)
             : base(IntPtr.Zero, true)
         {
@@ -159,18 +160,18 @@ internal SNIHandle(
                 }
 
                 _status = SNINativeMethodWrapper.SNIOpenSyncEx(myInfo, serverName, ref base.handle,
-                            spnBuffer, instanceName, flushCache, fSync, timeout, fParallel, cachedDNSInfo);
+                            spnBuffer, instanceName, flushCache, fSync, timeout, fParallel, ipPreference, cachedDNSInfo);
             }
         }
 
         // constructs SNI Handle for MARS session
-        internal SNIHandle(SNINativeMethodWrapper.ConsumerInfo myInfo, SNIHandle parent, SQLDNSInfo cachedDNSInfo) : base(IntPtr.Zero, true)
+        internal SNIHandle(SNINativeMethodWrapper.ConsumerInfo myInfo, SNIHandle parent, SqlConnectionIPAddressPreference ipPreference, SQLDNSInfo cachedDNSInfo) : base(IntPtr.Zero, true)
         {
             try
             { }
             finally
             {
-                _status = SNINativeMethodWrapper.SNIOpenMarsSession(myInfo, parent, ref base.handle, parent._fSync, cachedDNSInfo);
+                _status = SNINativeMethodWrapper.SNIOpenMarsSession(myInfo, parent, ref base.handle, parent._fSync, ipPreference, cachedDNSInfo);
             }
         }
 
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs
index f3299816ed..05bba67a5a 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs
@@ -792,7 +792,8 @@ private void ResetCancelAndProcessAttention()
             }
         }
 
-        internal abstract void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, bool flushCache, bool async, bool fParallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isIntegratedSecurity = false);
+        internal abstract void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, bool flushCache, bool async, bool fParallel, 
+                                SqlConnectionIPAddressPreference iPAddressPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isIntegratedSecurity = false);
 
         internal abstract void AssignPendingDNSInfo(string userProtocol, string DNSCacheKey, ref SQLDNSInfo pendingDNSInfo);
 
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs
index 24b0c960d8..6bf08b0336 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs
@@ -50,9 +50,11 @@ internal SNIMarsHandle CreateMarsSession(object callbackObject, bool async)
         protected override uint SNIPacketGetData(PacketHandle packet, byte[] _inBuff, ref uint dataSize)
             => SNIProxy.GetInstance().PacketGetData(packet.ManagedPacket, _inBuff, ref dataSize);
 
-        internal override void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, bool flushCache, bool async, bool parallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isIntegratedSecurity)
+        internal override void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, bool flushCache, bool async, bool parallel, 
+                                           SqlConnectionIPAddressPreference iPAddressPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isIntegratedSecurity)
         {
-            _sessionHandle = SNIProxy.GetInstance().CreateConnectionHandle(serverName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref spnBuffer, flushCache, async, parallel, isIntegratedSecurity, cachedFQDN, ref pendingDNSInfo);
+            _sessionHandle = SNIProxy.GetInstance().CreateConnectionHandle(serverName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref spnBuffer, flushCache, async, parallel, isIntegratedSecurity, 
+                                                        iPAddressPreference, cachedFQDN, ref pendingDNSInfo);
             if (_sessionHandle == null)
             {
                 _parser.ProcessSNIError(this);
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs
index 34c7910dde..ecb6e0bb43 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs
@@ -66,7 +66,7 @@ protected override void CreateSessionHandle(TdsParserStateObject physicalConnect
             SQLDNSInfo cachedDNSInfo;
             bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(_parser.FQDNforDNSCahce, out cachedDNSInfo);
 
-            _sessionHandle = new SNIHandle(myInfo, nativeSNIObject.Handle, cachedDNSInfo);
+            _sessionHandle = new SNIHandle(myInfo, nativeSNIObject.Handle, _parser.Connection.ConnectionOptions.IPAddressPreference, cachedDNSInfo);
         }
 
         internal override void AssignPendingDNSInfo(string userProtocol, string DNSCacheKey, ref SQLDNSInfo pendingDNSInfo)
@@ -137,7 +137,8 @@ private SNINativeMethodWrapper.ConsumerInfo CreateConsumerInfo(bool async)
             return myInfo;
         }
 
-        internal override void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, bool flushCache, bool async, bool fParallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isIntegratedSecurity)
+        internal override void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, bool flushCache, bool async, bool fParallel,
+                         SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isIntegratedSecurity)
         {
             // We assume that the loadSSPILibrary has been called already. now allocate proper length of buffer
             spnBuffer = new byte[1][];
@@ -171,7 +172,7 @@ internal override void CreatePhysicalSNIHandle(string serverName, bool ignoreSni
             SQLDNSInfo cachedDNSInfo;
             bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out cachedDNSInfo);
 
-            _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer[0], ignoreSniOpenTimeout, checked((int)timeout), out instanceName, flushCache, !async, fParallel, cachedDNSInfo);
+            _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer[0], ignoreSniOpenTimeout, checked((int)timeout), out instanceName, flushCache, !async, fParallel, ipPreference, cachedDNSInfo);
         }
 
         protected override uint SNIPacketGetData(PacketHandle packet, byte[] _inBuff, ref uint dataSize)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs
index 8a95a52351..9318d7eb40 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs
@@ -4442,6 +4442,12 @@ internal static string TCE_DbConnectionString_AttestationProtocol {
                 return ResourceManager.GetString("TCE_DbConnectionString_AttestationProtocol", resourceCulture);
             }
         }
+
+        /// 
+        ///   Looks up a localized string similar to Specifies an IP address preference when connecting to SQL instances.
+        /// 
+        internal static string TCE_DbConnectionString_IPAddressPreference
+            => ResourceManager.GetString("TCE_DbConnectionString_IPAddressPreference", resourceCulture);
         
         /// 
         ///   Looks up a localized string similar to Decryption failed. The last 10 bytes of the encrypted column encryption key are: '{0}'. The first 10 bytes of ciphertext are: '{1}'..
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx
index 5dd36f38ac..335803c097 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx
@@ -1851,6 +1851,9 @@
   
     Specifies an attestation protocol for its corresponding enclave attestation service.
   
+  
+    Specifies an IP address preference when connecting to SQL instances.
+  
   
     The enclave type '{0}' returned from the server is not supported.
   
diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs
index 23c88ff5b5..7e35b64c04 100644
--- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs
@@ -888,6 +888,19 @@ public enum SqlConnectionAttestationProtocol
         HGS = 3
     }
 
+    /// 
+    public enum SqlConnectionIPAddressPreference
+    {
+        /// 
+        IPv4First = 0,  // default
+
+        /// 
+        IPv6First = 1,
+
+        /// 
+        UsePlatformDefault = 2
+    }
+
     /// 
     public enum SqlConnectionOverrides
     {
@@ -974,6 +987,10 @@ public SqlConnectionStringBuilder(string connectionString) { }
         [System.ComponentModel.DisplayNameAttribute("Attestation Protocol")]
         [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
         public Microsoft.Data.SqlClient.SqlConnectionAttestationProtocol AttestationProtocol { get { throw null; } set { } }
+        /// 
+        [System.ComponentModel.DisplayNameAttribute("IP Address Preference")]
+        [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
+        public Microsoft.Data.SqlClient.SqlConnectionIPAddressPreference IPAddressPreference { get { throw null; } set { } }
         /// 
         [System.ComponentModel.DisplayNameAttribute("Encrypt")]
         [System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionStringCommon.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionStringCommon.cs
index 71ab0deea3..ec0bd3a558 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionStringCommon.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionStringCommon.cs
@@ -998,6 +998,110 @@ internal static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(st
 
         #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
+
         internal static bool IsValidCertificateValue(string value)
         {
             return string.IsNullOrEmpty(value)
@@ -1065,6 +1169,7 @@ internal static class DbConnectionStringDefaults
         internal static readonly SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
         internal const string EnclaveAttestationUrl = _emptyString;
         internal const SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified;
+        internal const SqlConnectionIPAddressPreference IPAddressPreference = SqlConnectionIPAddressPreference.IPv4First;
         internal const string Certificate = _emptyString;
         internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto;
     }
@@ -1139,6 +1244,7 @@ internal static class DbConnectionStringKeywords
         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 PoolBlockingPeriod = "Pool Blocking Period";
 
         // common keywords (OleDb, OracleClient, SqlClient)
@@ -1164,6 +1270,9 @@ internal static class DbConnectionStringSynonyms
         //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";
 
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs
index 0cddc32dc1..b28c736977 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs
@@ -101,6 +101,7 @@ internal static extern uint SNIOpenWrapper(
             [In] SNIHandle pConn,
             out IntPtr ppConn,
             [MarshalAs(UnmanagedType.Bool)] bool fSync,
+            SqlConnectionIPAddressPreference ipPreference,
             [In] ref SNI_DNSCache_Info pDNSCachedInfo);
 
         [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs
index 398ecc4872..2dc215ad36 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs
@@ -101,6 +101,7 @@ internal static extern uint SNIOpenWrapper(
             [In] SNIHandle pConn,
             out IntPtr ppConn,
             [MarshalAs(UnmanagedType.Bool)] bool fSync,
+            SqlConnectionIPAddressPreference ipPreference,
             [In] ref SNI_DNSCache_Info pDNSCachedInfo);
 
         [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs
index 0ac874b8b6..19dd12587a 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs
@@ -354,6 +354,7 @@ internal unsafe struct SNI_CLIENT_CONSUMER_INFO
             public TransparentNetworkResolutionMode transparentNetworkResolution;
             public int totalTimeout;
             public bool isAzureSqlServerEndpoint;
+            public SqlConnectionIPAddressPreference ipAddressPreference;
             public SNI_DNSCache_Info DNSCacheInfo;
         }
 
@@ -604,11 +605,12 @@ private static uint SNIOpenWrapper(
             [In] SNIHandle pConn,
             out IntPtr ppConn,
             [MarshalAs(UnmanagedType.Bool)] bool fSync,
+            SqlConnectionIPAddressPreference ipPreference,
             [In] ref SNI_DNSCache_Info pDNSCachedInfo)
         {
             return s_is64bitProcess ?
-                SNINativeManagedWrapperX64.SNIOpenWrapper(ref pConsumerInfo, szConnect, pConn, out ppConn, fSync, ref pDNSCachedInfo) :
-                SNINativeManagedWrapperX86.SNIOpenWrapper(ref pConsumerInfo, szConnect, pConn, out ppConn, fSync, ref pDNSCachedInfo);
+                SNINativeManagedWrapperX64.SNIOpenWrapper(ref pConsumerInfo, szConnect, pConn, out ppConn, fSync, ipPreference, ref pDNSCachedInfo) :
+                SNINativeManagedWrapperX86.SNIOpenWrapper(ref pConsumerInfo, szConnect, pConn, out ppConn, fSync, ipPreference, ref pDNSCachedInfo);
         }
 
         private static IntPtr SNIPacketAllocateWrapper([In] SafeHandle pConn, IOType IOType)
@@ -758,7 +760,7 @@ internal static uint SNIInitialize()
             return SNIInitialize(IntPtr.Zero);
         }
 
-        internal static unsafe uint SNIOpenMarsSession(ConsumerInfo consumerInfo, SNIHandle parent, ref IntPtr pConn, bool fSync, SQLDNSInfo cachedDNSInfo)
+        internal static unsafe uint SNIOpenMarsSession(ConsumerInfo consumerInfo, SNIHandle parent, ref IntPtr pConn, bool fSync, SqlConnectionIPAddressPreference ipPreference, SQLDNSInfo cachedDNSInfo)
         {
             // initialize consumer info for MARS
             Sni_Consumer_Info native_consumerInfo = new Sni_Consumer_Info();
@@ -770,10 +772,11 @@ internal static unsafe uint SNIOpenMarsSession(ConsumerInfo consumerInfo, SNIHan
             native_cachedDNSInfo.wszCachedTcpIPv6 = cachedDNSInfo?.AddrIPv6;
             native_cachedDNSInfo.wszCachedTcpPort = cachedDNSInfo?.Port;
 
-            return SNIOpenWrapper(ref native_consumerInfo, "session:", parent, out pConn, fSync, ref native_cachedDNSInfo);
+            return SNIOpenWrapper(ref native_consumerInfo, "session:", parent, out pConn, fSync, ipPreference, ref native_cachedDNSInfo);
         }
 
-        internal static unsafe uint SNIOpenSyncEx(ConsumerInfo consumerInfo, string constring, ref IntPtr pConn, byte[] spnBuffer, byte[] instanceName, bool fOverrideCache, bool fSync, int timeout, bool fParallel, Int32 transparentNetworkResolutionStateNo, Int32 totalTimeout, Boolean isAzureSqlServerEndpoint, SQLDNSInfo cachedDNSInfo)
+        internal static unsafe uint SNIOpenSyncEx(ConsumerInfo consumerInfo, string constring, ref IntPtr pConn, byte[] spnBuffer, byte[] instanceName, bool fOverrideCache, bool fSync, int timeout, bool fParallel, 
+                        Int32 transparentNetworkResolutionStateNo, Int32 totalTimeout, Boolean isAzureSqlServerEndpoint, SqlConnectionIPAddressPreference ipPreference, SQLDNSInfo cachedDNSInfo)
         {
             fixed (byte* pin_instanceName = &instanceName[0])
             {
@@ -808,6 +811,7 @@ internal static unsafe uint SNIOpenSyncEx(ConsumerInfo consumerInfo, string cons
                 };
                 clientConsumerInfo.totalTimeout = totalTimeout;
 
+                clientConsumerInfo.ipAddressPreference = ipPreference;
                 clientConsumerInfo.DNSCacheInfo.wszCachedFQDN = cachedDNSInfo?.FQDN;
                 clientConsumerInfo.DNSCacheInfo.wszCachedTcpIPv4 = cachedDNSInfo?.AddrIPv4;
                 clientConsumerInfo.DNSCacheInfo.wszCachedTcpIPv6 = cachedDNSInfo?.AddrIPv6;
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 f734ced9f8..3c9a6a4a1a 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
@@ -588,6 +588,14 @@ internal SqlConnectionAttestationProtocol AttestationProtocol
             }
         }
 
+        /// 
+        /// Get IP address preference
+        /// 
+        internal SqlConnectionIPAddressPreference iPAddressPreference
+        {
+            get => ((SqlConnectionString)ConnectionOptions).IPAddressPreference;
+        }
+
         // Is this connection is a Context Connection?
         private bool UsesContextConnection(SqlConnectionString opt)
         {
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionString.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionString.cs
index 2b3ffa9d70..761ab74751 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionString.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionString.cs
@@ -58,6 +58,7 @@ internal static class DEFAULT
             internal static readonly SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
             internal const string EnclaveAttestationUrl = _emptyString;
             internal static readonly SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified;
+            internal static readonly SqlConnectionIPAddressPreference s_IPAddressPreference = SqlConnectionIPAddressPreference.IPv4First;
 
 #if ADONET_CERT_AUTH
             internal const  string Certificate = _emptyString;
@@ -76,6 +77,7 @@ internal static class KEY
             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 Connect_Timeout = "connect timeout";
             internal const string Command_Timeout = "command timeout";
             internal const string Connection_Reset = "connection reset";
@@ -118,6 +120,8 @@ internal static class KEY
 
         private static class SYNONYM
         {
+            // ip address preference
+            internal const string IPADDRESSPREFERENCE = "ipaddresspreference";
             // application intent
             internal const string APPLICATIONINTENT = "applicationintent";
             // application name
@@ -172,7 +176,7 @@ private static class SYNONYM
             // make sure to update SynonymCount value below when adding or removing synonyms
         }
 
-        internal const int SynonymCount = 29;
+        internal const int SynonymCount = 30;
 
         // the following are all inserted as keys into the _netlibMapping hash
         internal static class NETLIB
@@ -239,6 +243,7 @@ internal static class TRANSACIONBINDING
         private readonly SqlConnectionColumnEncryptionSetting _columnEncryptionSetting;
         private readonly string _enclaveAttestationUrl;
         private readonly SqlConnectionAttestationProtocol _attestationProtocol;
+        private readonly SqlConnectionIPAddressPreference _ipAddressPreference;
 
         private readonly int _commandTimeout;
         private readonly int _connectTimeout;
@@ -325,6 +330,7 @@ internal SqlConnectionString(string connectionString) : base(connectionString, G
             _columnEncryptionSetting = ConvertValueToColumnEncryptionSetting();
             _enclaveAttestationUrl = ConvertValueToString(KEY.EnclaveAttestationUrl, DEFAULT.EnclaveAttestationUrl);
             _attestationProtocol = ConvertValueToAttestationProtocol();
+            _ipAddressPreference = ConvertValueToIPAddressPreference();
 
 #if ADONET_CERT_AUTH
             _certificate = ConvertValueToString(KEY.Certificate,         DEFAULT.Certificate);
@@ -682,6 +688,7 @@ internal SqlConnectionString(SqlConnectionString connectionOptions, string dataS
         internal SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting { get { return _columnEncryptionSetting; } }
         internal string EnclaveAttestationUrl { get { return _enclaveAttestationUrl; } }
         internal SqlConnectionAttestationProtocol AttestationProtocol { get { return _attestationProtocol; } }
+        internal SqlConnectionIPAddressPreference IPAddressPreference => _ipAddressPreference;
 #if ADONET_CERT_AUTH
         internal string Certificate { get { return _certificate; } }
         internal bool UsesCertificate { get { return _authType == SqlClient.SqlAuthenticationMethod.SqlCertificate; } }
@@ -822,6 +829,7 @@ internal static Hashtable GetParseSynonyms()
                 hash.Add(KEY.Connect_Retry_Count, KEY.Connect_Retry_Count);
                 hash.Add(KEY.Connect_Retry_Interval, KEY.Connect_Retry_Interval);
                 hash.Add(KEY.Authentication, KEY.Authentication);
+                hash.Add(KEY.IPAddressPreference, KEY.IPAddressPreference);
 #if ADONET_CERT_AUTH
                 hash.Add(KEY.Certificate,                    KEY.Certificate);
 #endif
@@ -854,6 +862,7 @@ internal static Hashtable GetParseSynonyms()
                 hash.Add(SYNONYM.UID, KEY.User_ID);
                 hash.Add(SYNONYM.User, KEY.User_ID);
                 hash.Add(SYNONYM.WSID, KEY.Workstation_Id);
+                hash.Add(SYNONYM.IPADDRESSPREFERENCE, KEY.IPAddressPreference);
                 Debug.Assert(SqlConnectionStringBuilder.KeywordsCount + SynonymCount == hash.Count, "incorrect initial ParseSynonyms size");
                 _sqlClientSynonyms = hash;
             }
@@ -1077,6 +1086,34 @@ internal SqlConnectionAttestationProtocol ConvertValueToAttestationProtocol()
             }
         }
 
+        /// 
+        /// Convert the value to SqlConnectionIPAddressPreference
+        /// 
+        /// 
+        internal SqlConnectionIPAddressPreference ConvertValueToIPAddressPreference()
+        {
+            object value = base.Parsetable[KEY.IPAddressPreference];
+
+            string valStr = value as string;
+            if (valStr == null)
+            {
+                return DEFAULT.s_IPAddressPreference;
+            }
+
+            try
+            {
+                return DbConnectionStringBuilderUtil.ConvertToIPAddressPreference(KEY.IPAddressPreference, valStr);
+            }
+            catch (FormatException e)
+            {
+                throw ADP.InvalidConnectionOptionValue(KEY.IPAddressPreference, e);
+            }
+            catch (OverflowException e)
+            {
+                throw ADP.InvalidConnectionOptionValue(KEY.IPAddressPreference, e);
+            }
+        }
+
         internal bool ConvertValueToEncrypt()
         {
             // If the Authentication keyword is provided, default to Encrypt=true;
@@ -1087,4 +1124,3 @@ internal bool ConvertValueToEncrypt()
         }
     }
 }
-
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
index 17d62e41bd..15590fe981 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs
@@ -65,6 +65,7 @@ private enum Keywords
             AttestationProtocol,
 
             CommandTimeout,
+            IPAddressPreference,
 
 #if ADONET_CERT_AUTH
             Certificate,
@@ -118,6 +119,7 @@ private enum Keywords
         private SqlConnectionColumnEncryptionSetting _columnEncryptionSetting = DbConnectionStringDefaults.ColumnEncryptionSetting;
         private string _enclaveAttestationUrl = DbConnectionStringDefaults.EnclaveAttestationUrl;
         private SqlConnectionAttestationProtocol _attestationProtocol = DbConnectionStringDefaults.AttestationProtocol;
+        private SqlConnectionIPAddressPreference _ipAddressPreference = DbConnectionStringDefaults.IPAddressPreference;
         private PoolBlockingPeriod _poolBlockingPeriod = DbConnectionStringDefaults.PoolBlockingPeriod;
 
 #if ADONET_CERT_AUTH
@@ -168,6 +170,7 @@ static SqlConnectionStringBuilder()
             validKeywords[(int)Keywords.ColumnEncryptionSetting] = DbConnectionStringKeywords.ColumnEncryptionSetting;
             validKeywords[(int)Keywords.EnclaveAttestationUrl] = DbConnectionStringKeywords.EnclaveAttestationUrl;
             validKeywords[(int)Keywords.AttestationProtocol] = DbConnectionStringKeywords.AttestationProtocol;
+            validKeywords[(int)Keywords.IPAddressPreference] = DbConnectionStringKeywords.IPAddressPreference;
 #if ADONET_CERT_AUTH
             validKeywords[(int)Keywords.Certificate] = DbConnectionStringKeywords.Certificate;
 #endif
@@ -215,9 +218,11 @@ static SqlConnectionStringBuilder()
             hash.Add(DbConnectionStringKeywords.ColumnEncryptionSetting, Keywords.ColumnEncryptionSetting);
             hash.Add(DbConnectionStringKeywords.EnclaveAttestationUrl, Keywords.EnclaveAttestationUrl);
             hash.Add(DbConnectionStringKeywords.AttestationProtocol, Keywords.AttestationProtocol);
+            hash.Add(DbConnectionStringKeywords.IPAddressPreference, Keywords.IPAddressPreference);
 #if ADONET_CERT_AUTH
             hash.Add(DbConnectionStringKeywords.Certificate, Keywords.Certificate);
 #endif
+            hash.Add(DbConnectionStringSynonyms.IPADDRESSPREFERENCE, Keywords.IPAddressPreference);
             hash.Add(DbConnectionStringSynonyms.APP, Keywords.ApplicationName);
             hash.Add(DbConnectionStringSynonyms.APPLICATIONINTENT, Keywords.ApplicationIntent);
             hash.Add(DbConnectionStringSynonyms.Async, Keywords.AsynchronousProcessing);
@@ -357,6 +362,9 @@ public override object this[string keyword]
                         case Keywords.AttestationProtocol:
                             AttestationProtocol = ConvertToAttestationProtocol(keyword, value);
                             break;
+                        case Keywords.IPAddressPreference:
+                            IPAddressPreference = ConvertToIPAddressPreference(keyword, value);
+                            break;
 #if ADONET_CERT_AUTH
                         case Keywords.Certificate:
                             Certificate = ConvertToString(value);
@@ -688,6 +696,26 @@ public SqlConnectionAttestationProtocol AttestationProtocol
             }
         }
 
+        /// 
+        [DisplayName(DbConnectionStringKeywords.IPAddressPreference)]
+        [ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Security)]
+        [ResDescriptionAttribute(StringsHelper.ResourceNames.TCE_DbConnectionString_IPAddressPreference)]
+        [RefreshPropertiesAttribute(RefreshProperties.All)]
+        public SqlConnectionIPAddressPreference IPAddressPreference
+        {
+            get => _ipAddressPreference;
+            set
+            {
+                if (!DbConnectionStringBuilderUtil.IsValidIPAddressPreference(value))
+                {
+                    throw ADP.InvalidEnumerationValue(typeof(SqlConnectionIPAddressPreference), (int)value);
+                }
+
+                SetIPAddressPreferenceValue(value);
+                _ipAddressPreference = value;
+            }
+        }
+
         /// 
         [DisplayName(DbConnectionStringKeywords.TrustServerCertificate)]
         [ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Security)]
@@ -1267,6 +1295,14 @@ private static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(str
             return DbConnectionStringBuilderUtil.ConvertToAttestationProtocol(keyword, value);
         }
 
+        /// 
+        /// Convert to SqlConnectionIPAddressPreference
+        /// 
+        /// 
+        /// 
+        private static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(string keyword, object value)
+            => DbConnectionStringBuilderUtil.ConvertToIPAddressPreference(keyword, value);
+
         private object GetAt(Keywords index)
         {
             switch (index)
@@ -1357,6 +1393,8 @@ private object GetAt(Keywords index)
                     return EnclaveAttestationUrl;
                 case Keywords.AttestationProtocol:
                     return AttestationProtocol;
+                case Keywords.IPAddressPreference:
+                    return IPAddressPreference;
 #if ADONET_CERT_AUTH
             case Keywords.Certificate:              return Certificate;
 #endif
@@ -1552,6 +1590,9 @@ private void Reset(Keywords index)
                 case Keywords.AttestationProtocol:
                     _attestationProtocol = DbConnectionStringDefaults.AttestationProtocol;
                     break;
+                case Keywords.IPAddressPreference:
+                    _ipAddressPreference = DbConnectionStringDefaults.IPAddressPreference;
+                    break;
                 default:
                     Debug.Fail("unexpected keyword");
                     throw ADP.KeywordNotSupported(_validKeywords[(int)index]);
@@ -1598,6 +1639,12 @@ private void SetAttestationProtocolValue(SqlConnectionAttestationProtocol value)
             base[DbConnectionStringKeywords.AttestationProtocol] = DbConnectionStringBuilderUtil.AttestationProtocolToString(value);
         }
 
+        private void SetIPAddressPreferenceValue(SqlConnectionIPAddressPreference value)
+        {
+            Debug.Assert(DbConnectionStringBuilderUtil.IsValidIPAddressPreference(value), "Invalid value for SqlConnectionIPAddressPreference");
+            base[DbConnectionStringKeywords.IPAddressPreference] = DbConnectionStringBuilderUtil.IPAddressPreferenceToString(value);
+        }
+
 
         /// 
         public override bool ShouldSerialize(string keyword)
@@ -1923,4 +1970,3 @@ private System.ComponentModel.Design.Serialization.InstanceDescriptor ConvertToI
     }
 
 }
-
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsEnums.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsEnums.cs
index 5e422fef74..4ac0a23fa4 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsEnums.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsEnums.cs
@@ -1076,6 +1076,19 @@ public enum SqlConnectionAttestationProtocol
         HGS = 3
     }
 
+    /// 
+    public enum SqlConnectionIPAddressPreference
+    {
+        /// 
+        IPv4First = 0,  // default
+
+        /// 
+        IPv6First = 1,
+
+        /// 
+        UsePlatformDefault = 2
+    }
+
     /// 
     public enum SqlAuthenticationMethod
     {
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs
index 6b4d322c1f..78015db428 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs
@@ -593,7 +593,7 @@ internal void Connect(ServerInfo serverInfo,
             }
 
             _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire,
-                        out instanceName, _sniSpnBuffer, false, true, fParallel, transparentNetworkResolutionState, totalTimeout, FQDNforDNSCahce);
+                        out instanceName, _sniSpnBuffer, false, true, fParallel, transparentNetworkResolutionState, totalTimeout, _connHandler.ConnectionOptions.IPAddressPreference, FQDNforDNSCahce);
 
             if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status)
             {
@@ -656,7 +656,8 @@ internal void Connect(ServerInfo serverInfo,
 
                 // On Instance failure re-connect and flush SNI named instance cache.
                 _physicalStateObj.SniContext = SniContext.Snix_Connect;
-                _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, _sniSpnBuffer, true, true, fParallel, transparentNetworkResolutionState, totalTimeout, serverInfo.ResolvedServerName);
+                _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, 
+                            out instanceName, _sniSpnBuffer, true, true, fParallel, transparentNetworkResolutionState, totalTimeout, _connHandler.ConnectionOptions.IPAddressPreference, serverInfo.ResolvedServerName);
 
                 if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status)
                 {
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.cs
index 30e874995c..b61ed1dd34 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.cs
@@ -150,6 +150,7 @@ internal SNIHandle(
             bool fParallel,
             TransparentNetworkResolutionState transparentNetworkResolutionState,
             int totalTimeout,
+            SqlConnectionIPAddressPreference ipPreference,
             SQLDNSInfo cachedDNSInfo)
             : base(IntPtr.Zero, true)
         {
@@ -172,19 +173,19 @@ internal SNIHandle(
                 int transparentNetworkResolutionStateNo = (int)transparentNetworkResolutionState;
                 _status = SNINativeMethodWrapper.SNIOpenSyncEx(myInfo, serverName, ref base.handle,
                             spnBuffer, instanceName, flushCache, fSync, timeout, fParallel, transparentNetworkResolutionStateNo, totalTimeout,
-                            ADP.IsAzureSqlServerEndpoint(serverName), cachedDNSInfo);
+                            ADP.IsAzureSqlServerEndpoint(serverName), ipPreference, cachedDNSInfo);
             }
         }
 
         // constructs SNI Handle for MARS session
-        internal SNIHandle(SNINativeMethodWrapper.ConsumerInfo myInfo, SNIHandle parent, SQLDNSInfo cachedDNSInfo) : base(IntPtr.Zero, true)
+        internal SNIHandle(SNINativeMethodWrapper.ConsumerInfo myInfo, SNIHandle parent, SqlConnectionIPAddressPreference ipPreference, SQLDNSInfo cachedDNSInfo) : base(IntPtr.Zero, true)
         {
             RuntimeHelpers.PrepareConstrainedRegions();
             try
             { }
             finally
             {
-                _status = SNINativeMethodWrapper.SNIOpenMarsSession(myInfo, parent, ref base.handle, parent._fSync, cachedDNSInfo);
+                _status = SNINativeMethodWrapper.SNIOpenMarsSession(myInfo, parent, ref base.handle, parent._fSync, ipPreference, cachedDNSInfo);
             }
         }
 
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs
index ebd75aaefa..9453f6102a 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs
@@ -326,7 +326,7 @@ internal TdsParserStateObject(TdsParser parser, SNIHandle physicalConnection, bo
             SQLDNSInfo cachedDNSInfo;
             bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(_parser.FQDNforDNSCahce, out cachedDNSInfo);
 
-            _sessionHandle = new SNIHandle(myInfo, physicalConnection, cachedDNSInfo);
+            _sessionHandle = new SNIHandle(myInfo, physicalConnection, _parser.Connection.ConnectionOptions.IPAddressPreference, cachedDNSInfo);
             if (_sessionHandle.Status != TdsEnums.SNI_SUCCESS)
             {
                 AddError(parser.ProcessSNIError(this));
@@ -852,7 +852,8 @@ private SNINativeMethodWrapper.ConsumerInfo CreateConsumerInfo(bool async)
             return myInfo;
         }
 
-        internal void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, byte[] spnBuffer, bool flushCache, bool async, bool fParallel, TransparentNetworkResolutionState transparentNetworkResolutionState, int totalTimeout, string cachedFQDN)
+        internal void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, byte[] spnBuffer, bool flushCache, 
+                bool async, bool fParallel, TransparentNetworkResolutionState transparentNetworkResolutionState, int totalTimeout, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN)
         {
             SNINativeMethodWrapper.ConsumerInfo myInfo = CreateConsumerInfo(async);
 
@@ -880,7 +881,8 @@ internal void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeo
             SQLDNSInfo cachedDNSInfo;
             bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out cachedDNSInfo);
 
-            _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer, ignoreSniOpenTimeout, checked((int)timeout), out instanceName, flushCache, !async, fParallel, transparentNetworkResolutionState, totalTimeout, cachedDNSInfo);
+            _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer, ignoreSniOpenTimeout, checked((int)timeout), 
+                    out instanceName, flushCache, !async, fParallel, transparentNetworkResolutionState, totalTimeout, ipPreference, cachedDNSInfo);
         }
 
         internal bool Deactivate()
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs
index 925c38901d..f5b5f44a4c 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs
@@ -12077,6 +12077,12 @@ internal static string TCE_DbConnectionString_AttestationProtocol {
                 return ResourceManager.GetString("TCE_DbConnectionString_AttestationProtocol", resourceCulture);
             }
         }
+
+        /// 
+        ///   Looks up a localized string similar to Specifies an IP address preference when connecting to SQL instances.
+        /// 
+        internal static string TCE_DbConnectionString_IPAddressPreference
+            => ResourceManager.GetString("TCE_DbConnectionString_IPAddressPreference", resourceCulture);
         
         /// 
         ///   Looks up a localized string similar to Default column encryption setting for all the commands on the connection..
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx
index 1ffcff4d0b..7ca22b2fe8 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx
@@ -4524,6 +4524,9 @@
   
     Specifies an attestation protocol for its corresponding enclave attestation service.
   
+  
+    Specifies an IP address preference when connecting to SQL instances.
+  
   
     The enclave type '{0}' returned from the server is not supported.
   
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SQLFallbackDNSCache.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SQLFallbackDNSCache.cs
index e18b61cee4..9d4136d01f 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SQLFallbackDNSCache.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SQLFallbackDNSCache.cs
@@ -7,7 +7,7 @@
 
 namespace Microsoft.Data.SqlClient
 {
-    internal class SQLFallbackDNSCache
+    internal sealed class SQLFallbackDNSCache
     {
         private static readonly SQLFallbackDNSCache _SQLFallbackDNSCache = new SQLFallbackDNSCache();
         private static readonly int initialCapacity = 101;   // give some prime number here according to MSDN docs. It will be resized if reached capacity. 
@@ -68,7 +68,7 @@ internal bool IsDuplicate(SQLDNSInfo newItem)
         }
     }
 
-    internal class SQLDNSInfo
+    internal sealed class SQLDNSInfo
     {
         public string FQDN { get; set; }
         public string AddrIPv4 { get; set; }
diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs
index 9796b297c2..4a61e10edd 100644
--- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs
@@ -55,6 +55,9 @@ public partial class SqlConnectionStringBuilderTest
         [InlineData("Initial Catalog = Northwind; Failover Partner = randomserver.sys.local")]
         [InlineData("Initial Catalog = tempdb")]
         [InlineData("Integrated Security = true")]
+        [InlineData("IPAddressPreference = IPv4First")]
+        [InlineData("IPAddressPreference = IPv6First")]
+        [InlineData("IPAddressPreference = UsePlatformDefault")]
         [InlineData("Trusted_Connection = false")]
         [InlineData("Max Pool Size = 50")]
         [InlineData("Min Pool Size = 20")]
diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs
index 9289f23768..b3afc51527 100644
--- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs
@@ -11,7 +11,7 @@ namespace Microsoft.Data.SqlClient.Tests
 {
     public partial class SqlConnectionTest
     {
-        private static readonly string[] s_retrieveInternalInfoKeys = 
+        private static readonly string[] s_retrieveInternalInfoKeys =
         {
             "SQLDNSCachingSupportedState",
             "SQLDNSCachingSupportedStateBeforeRedirect"
@@ -53,7 +53,7 @@ public void Constructor2()
             Assert.Null(cn.Site);
             Assert.Equal(ConnectionState.Closed, cn.State);
             Assert.False(cn.StatisticsEnabled);
-            Assert.True(string.Compare (Environment.MachineName, cn.WorkstationId, true) == 0);
+            Assert.True(string.Compare(Environment.MachineName, cn.WorkstationId, true) == 0);
 
             cn = new SqlConnection((string)null);
             Assert.Equal(string.Empty, cn.ConnectionString);
@@ -67,7 +67,7 @@ public void Constructor2()
             Assert.Null(cn.Site);
             Assert.Equal(ConnectionState.Closed, cn.State);
             Assert.False(cn.StatisticsEnabled);
-            Assert.True(string.Compare (Environment.MachineName, cn.WorkstationId, true) == 0);
+            Assert.True(string.Compare(Environment.MachineName, cn.WorkstationId, true) == 0);
         }
 
         [Fact]
@@ -107,7 +107,7 @@ public void Constructor2_ConnectionString_Invalid()
             try
             {
                 new SqlConnection("Packet Size=511");
-           }
+            }
             catch (ArgumentException ex)
             {
                 // Invalid 'Packet Size'.  The value must be an
@@ -1326,7 +1326,7 @@ public void RetrieveInternalInfo_ExpectedKeysInDictionary_Success()
             Assert.NotEmpty(d.Values);
             Assert.Equal(s_retrieveInternalInfoKeys.Length, d.Values.Count);
 
-            foreach(string key in s_retrieveInternalInfoKeys)
+            foreach (string key in s_retrieveInternalInfoKeys)
             {
                 Assert.True(d.ContainsKey(key));
 
@@ -1343,5 +1343,48 @@ public void RetrieveInternalInfo_UnexpectedKeysInDictionary_Success()
             IDictionary d = cn.RetrieveInternalInfo();
             Assert.False(d.ContainsKey("Foo"));
         }
+
+        [Fact]
+        public void ConnectionString_IPAddressPreference()
+        {
+            SqlConnection cn = new SqlConnection();
+            cn.ConnectionString = "IPAddressPreference=IPv4First";
+            cn.ConnectionString = "IPAddressPreference=IPV4FIRST";
+            cn.ConnectionString = "IPAddressPreference=ipv4first";
+            cn.ConnectionString = "IPAddressPreference=iPv4FirSt";
+            cn.ConnectionString = "IPAddressPreference=IPv6First";
+            cn.ConnectionString = "IPAddressPreference=IPV6FIRST";
+            cn.ConnectionString = "IPAddressPreference=ipv6first";
+            cn.ConnectionString = "IPAddressPreference=iPv6FirST";
+            cn.ConnectionString = "IPAddressPreference=UsePlatformDefault";
+            cn.ConnectionString = "IPAddressPreference=USEPLATFORMDEFAULT";
+            cn.ConnectionString = "IPAddressPreference=useplatformdefault";
+            cn.ConnectionString = "IPAddressPreference=usePlAtFormdeFault";
+        }
+
+        [Theory]
+        [InlineData("IPAddressPreference=-1")]
+        [InlineData("IPAddressPreference=0")]
+        [InlineData("IPAddressPreference=!@#")]
+        [InlineData("IPAddressPreference=ABC")]
+        [InlineData("IPAddressPreference=ipv6")]
+        public void ConnectionString_IPAddressPreference_Invalid(string value)
+        {
+            SqlConnection cn = new SqlConnection();
+            try
+            {
+                cn.ConnectionString = value;
+                Assert.True(false, $"It mustn't come to this line; Value '{value}' should be invalid.");
+            }
+            catch (ArgumentException ex)
+            {
+                // Invalid value for key 'ip address preference'
+                Assert.Equal(typeof(ArgumentException), ex.GetType());
+                Assert.Null(ex.InnerException);
+                Assert.NotNull(ex.Message);
+                Assert.Contains("'ip address preference'", ex.Message);
+                Assert.Null(ex.ParamName);
+            }
+        }
     }
 }
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
index a97a16a05d..2aefb3fe36 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
@@ -9,6 +9,9 @@
 using System.Diagnostics.Tracing;
 using System.Globalization;
 using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
 using System.Security;
 using System.Threading;
 using System.Threading.Tasks;
@@ -343,6 +346,20 @@ public static bool IsTCPConnectionStringPasswordIncluded()
             return RetrieveValueFromConnStr(TCPConnectionString, new string[] { "Password", "PWD" }) != string.Empty;
         }
 
+        public static bool DoesHostAddressContainBothIPv4AndIPv6()
+        {
+            if (!IsDNSCachingSetup())
+            {
+                return false;
+            }
+            using (var connection = new SqlConnection(DNSCachingConnString))
+            {
+                List ipAddresses = Dns.GetHostAddresses(connection.DataSource).ToList();
+                return ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetwork) &&
+                    ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetworkV6);
+            }
+        }
+
         /// 
         /// Generate a unique name to use in Sql Server; 
         /// some providers does not support names (Oracle supports up to 30).
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj
index 0878e72f74..0a1946d7cc 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj
@@ -70,6 +70,7 @@
       Common\System\Collections\DictionaryExtensions.cs
     
     
+    
     
     
     
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncCancelledConnectionsTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncCancelledConnectionsTest.cs
index 2e2a1ca022..e71d6d62f6 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncCancelledConnectionsTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncCancelledConnectionsTest.cs
@@ -28,18 +28,14 @@ public void CancelAsyncConnections()
         {
             SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString);
             builder.MultipleActiveResultSets = false;
-            RunCancelAsyncConnections(builder, false);
-            RunCancelAsyncConnections(builder, true);
+            RunCancelAsyncConnections(builder);
             builder.MultipleActiveResultSets = true;
-            RunCancelAsyncConnections(builder, false);
-            RunCancelAsyncConnections(builder, true);
+            RunCancelAsyncConnections(builder);
         }
 
-        private void RunCancelAsyncConnections(SqlConnectionStringBuilder connectionStringBuilder, bool makeAsyncBlocking)
+        private void RunCancelAsyncConnections(SqlConnectionStringBuilder connectionStringBuilder)
         {
             SqlConnection.ClearAllPools();
-            AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking", makeAsyncBlocking);
-
             _watch = Stopwatch.StartNew();
             _random = new Random(4); // chosen via fair dice role.
             ParallelLoopResult results = new ParallelLoopResult();
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Common/SystemDataInternals/ConnectionHelper.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Common/SystemDataInternals/ConnectionHelper.cs
index 54561e1be9..32bac50d08 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Common/SystemDataInternals/ConnectionHelper.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Common/SystemDataInternals/ConnectionHelper.cs
@@ -17,6 +17,7 @@ internal static class ConnectionHelper
         private static Type s_dbConnectionInternal = s_MicrosoftDotData.GetType("Microsoft.Data.ProviderBase.DbConnectionInternal");
         private static Type s_tdsParser = s_MicrosoftDotData.GetType("Microsoft.Data.SqlClient.TdsParser");
         private static Type s_tdsParserStateObject = s_MicrosoftDotData.GetType("Microsoft.Data.SqlClient.TdsParserStateObject");
+        private static Type s_SQLDNSInfo = s_MicrosoftDotData.GetType("Microsoft.Data.SqlClient.SQLDNSInfo");
         private static PropertyInfo s_sqlConnectionInternalConnection = s_sqlConnection.GetProperty("InnerConnection", BindingFlags.Instance | BindingFlags.NonPublic);
         private static PropertyInfo s_dbConnectionInternalPool = s_dbConnectionInternal.GetProperty("Pool", BindingFlags.Instance | BindingFlags.NonPublic);
         private static MethodInfo s_dbConnectionInternalIsConnectionAlive = s_dbConnectionInternal.GetMethod("IsConnectionAlive", BindingFlags.Instance | BindingFlags.NonPublic);
@@ -26,6 +27,11 @@ internal static class ConnectionHelper
         private static FieldInfo s_tdsParserStateObjectProperty = s_tdsParser.GetField("_physicalStateObj", BindingFlags.Instance | BindingFlags.NonPublic);
         private static FieldInfo s_enforceTimeoutDelayProperty = s_tdsParserStateObject.GetField("_enforceTimeoutDelay", BindingFlags.Instance | BindingFlags.NonPublic);
         private static FieldInfo s_enforcedTimeoutDelayInMilliSeconds = s_tdsParserStateObject.GetField("_enforcedTimeoutDelayInMilliSeconds", BindingFlags.Instance | BindingFlags.NonPublic);
+        private static FieldInfo s_pendingSQLDNSObject = s_sqlInternalConnectionTds.GetField("pendingSQLDNSObject", BindingFlags.Instance | BindingFlags.NonPublic);
+        private static PropertyInfo s_pendingSQLDNS_FQDN = s_SQLDNSInfo.GetProperty("FQDN", BindingFlags.Instance | BindingFlags.Public);
+        private static PropertyInfo s_pendingSQLDNS_AddrIPv4 = s_SQLDNSInfo.GetProperty("AddrIPv4", BindingFlags.Instance | BindingFlags.Public);
+        private static PropertyInfo s_pendingSQLDNS_AddrIPv6 = s_SQLDNSInfo.GetProperty("AddrIPv6", BindingFlags.Instance | BindingFlags.Public);
+        private static PropertyInfo s_pendingSQLDNS_Port = s_SQLDNSInfo.GetProperty("Port", BindingFlags.Instance | BindingFlags.Public);
 
         public static object GetConnectionPool(object internalConnection)
         {
@@ -79,5 +85,22 @@ public static void SetEnforcedTimeout(this SqlConnection connection, bool enforc
             s_enforceTimeoutDelayProperty.SetValue(stateObj, enforce);
             s_enforcedTimeoutDelayInMilliSeconds.SetValue(stateObj, timeout);
         }
+
+        /// 
+        /// Resolve the established socket end point information for TCP protocol.
+        /// 
+        /// Active connection to extract the requested data
+        /// FQDN, AddrIPv4, AddrIPv6, and Port in sequence
+        public static Tuple GetSQLDNSInfo(this SqlConnection connection)
+        {
+            object internalConnection = GetInternalConnection(connection);
+            VerifyObjectIsInternalConnection(internalConnection);
+            object pendingSQLDNSInfo = s_pendingSQLDNSObject.GetValue(internalConnection);
+            string fqdn = s_pendingSQLDNS_FQDN.GetValue(pendingSQLDNSInfo) as string;
+            string ipv4 = s_pendingSQLDNS_AddrIPv4.GetValue(pendingSQLDNSInfo) as string;
+            string ipv6 = s_pendingSQLDNS_AddrIPv6.GetValue(pendingSQLDNSInfo) as string;
+            string port = s_pendingSQLDNS_Port.GetValue(pendingSQLDNSInfo) as string;
+            return new Tuple(fqdn, ipv4, ipv6, port);
+        }
     }
 }
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConfigurableIpPreferenceTest/ConfigurableIpPreferenceTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConfigurableIpPreferenceTest/ConfigurableIpPreferenceTest.cs
new file mode 100644
index 0000000000..8003660889
--- /dev/null
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConfigurableIpPreferenceTest/ConfigurableIpPreferenceTest.cs
@@ -0,0 +1,125 @@
+// 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 System.Data;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using Microsoft.Data.SqlClient.ManualTesting.Tests.SystemDataInternals;
+using Xunit;
+
+using static Microsoft.Data.SqlClient.ManualTesting.Tests.DataTestUtility;
+using static Microsoft.Data.SqlClient.ManualTesting.Tests.DNSCachingTest;
+
+namespace Microsoft.Data.SqlClient.ManualTesting.Tests
+{
+    public class ConfigurableIpPreferenceTest
+    {
+        private const string CnnPrefIPv6 = ";IPAddressPreference=IPv6First";
+        private const string CnnPrefIPv4 = ";IPAddressPreference=IPv4First";
+
+        private static bool IsTCPConnectionStringSetup() => !string.IsNullOrEmpty(TCPConnectionString);
+        private static bool IsValidDataSource()
+        {
+            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(TCPConnectionString);
+            int startIdx = builder.DataSource.IndexOf(':') + 1;
+            int endIdx = builder.DataSource.IndexOf(',');
+            string serverName;
+            if (endIdx == -1)
+            {
+                serverName = builder.DataSource.Substring(startIdx);
+            }
+            else
+            {
+                serverName = builder.DataSource.Substring(startIdx, endIdx - startIdx);
+            }
+
+            List ipAddresses = Dns.GetHostAddresses(serverName).ToList();
+            return ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetwork) &&
+                    ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetworkV6);
+        }
+
+        [ConditionalTheory(nameof(IsTCPConnectionStringSetup), nameof(IsValidDataSource))]
+        [InlineData(CnnPrefIPv6)]
+        [InlineData(CnnPrefIPv4)]
+        [InlineData(";IPAddressPreference=UsePlatformDefault")]
+        public void ConfigurableIpPreference(string ipPreference)
+        {
+            using (SqlConnection connection = new SqlConnection(TCPConnectionString + ipPreference
+#if NETFRAMEWORK
+                + ";TransparentNetworkIPResolution=false"   // doesn't support in .NET Core
+#endif
+                ))
+            {
+                connection.Open();
+                Assert.Equal(ConnectionState.Open, connection.State);
+                Tuple DNSInfo = connection.GetSQLDNSInfo();
+                if(ipPreference == CnnPrefIPv4)
+                {
+                    Assert.NotNull(DNSInfo.Item2); //IPv4
+                    Assert.Null(DNSInfo.Item3); //IPv6
+                }
+                else if(ipPreference == CnnPrefIPv6)
+                {
+                    Assert.Null(DNSInfo.Item2);
+                    Assert.NotNull(DNSInfo.Item3);
+                }
+                else
+                {
+                    Assert.True((DNSInfo.Item2 != null && DNSInfo.Item3 == null) || (DNSInfo.Item2 == null && DNSInfo.Item3 != null));
+                }
+            }
+        }
+
+        // Azure SQL Server doesn't support dual-stack IPv4 and IPv6 that is going to be supported by end of 2021.
+        [ConditionalTheory(typeof(DataTestUtility), nameof(DoesHostAddressContainBothIPv4AndIPv6), nameof(IsUsingManagedSNI))]
+        [InlineData(CnnPrefIPv6)]
+        [InlineData(CnnPrefIPv4)]
+        public void ConfigurableIpPreferenceManagedSni(string ipPreference)
+            => TestCachedConfigurableIpPreference(ipPreference, DNSCachingConnString);
+
+        private void TestCachedConfigurableIpPreference(string ipPreference, string cnnString)
+        {
+            using (SqlConnection connection = new SqlConnection(cnnString + ipPreference))
+            {
+                // each successful connection updates the dns cache entry for the data source
+                connection.Open();
+                var SQLFallbackDNSCacheInstance = GetDnsCache();
+
+                // get the dns cache entry with the given key. parameters[1] will be initialized as the entry
+                object[] parameters = new object[] { connection.DataSource, null };
+                SQLFallbackDNSCacheGetDNSInfo.Invoke(SQLFallbackDNSCacheInstance, parameters);
+                var dnsCacheEntry = parameters[1];
+
+                const string AddrIPv4Property = "AddrIPv4";
+                const string AddrIPv6Property = "AddrIPv6";
+                const string FQDNProperty = "FQDN";
+
+                Assert.NotNull(dnsCacheEntry);
+                Assert.Equal(connection.DataSource, GetPropertyValueFromCacheEntry(FQDNProperty, dnsCacheEntry));
+
+                if (ipPreference == CnnPrefIPv4)
+                {
+                    Assert.NotNull(GetPropertyValueFromCacheEntry(AddrIPv4Property, dnsCacheEntry));
+                    Assert.Null(GetPropertyValueFromCacheEntry(AddrIPv6Property, dnsCacheEntry));
+                }
+                else if (ipPreference == CnnPrefIPv6)
+                {
+                    string ipv6 = GetPropertyValueFromCacheEntry(AddrIPv6Property, dnsCacheEntry);
+                    Assert.NotNull(ipv6);
+                    Assert.Null(GetPropertyValueFromCacheEntry(AddrIPv4Property, dnsCacheEntry));
+                }
+            }
+
+            object GetDnsCache() =>
+               SQLFallbackDNSCacheType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public).GetValue(null);
+
+            string GetPropertyValueFromCacheEntry(string property, object dnsCacheEntry) =>
+               (string)SQLDNSInfoType.GetProperty(property).GetValue(dnsCacheEntry);
+        }
+    }
+}
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DNSCachingTest/DNSCachingTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DNSCachingTest/DNSCachingTest.cs
index 33460acb8d..a23efff073 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DNSCachingTest/DNSCachingTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DNSCachingTest/DNSCachingTest.cs
@@ -4,7 +4,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.Reflection;
 using Xunit;
 
diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json
index 4c725d8555..6c631187b5 100644
--- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json
+++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json
@@ -18,6 +18,11 @@
     "SupportsLocalDb": false,
     "SupportsFileStream": false,
     "UseManagedSNIOnWindows": false,
+    "DNSCachingConnString": "",
+    "DNSCachingServerCR": "",
+    "DNSCachingServerTR": "",
+    "IsDNSCachingSupportedCR": false,
+    "IsDNSCachingSupportedTR": false,
     "IsAzureSynapse": false,
     "EnclaveAzureDatabaseConnString": "",
     "UserManagedIdentityClientId": ""