diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs index 2c3c2aeaf3..2889ce6bb4 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs @@ -68,7 +68,7 @@ public SNINpHandle(string serverName, string pipeName, TimeoutTimer timeout, boo { int timeoutMilliseconds = timeout.MillisecondsRemainingInt; SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, - "Connection Id {0}, Setting server name = {1}, pipe name = {2}. Connecting within the {3} sepecified milliseconds.", + "Connection Id {0}, Setting server name = {1}, pipe name = {2}. Connecting within the {3} specified milliseconds.", args0: _connectionId, args1: serverName, args2: pipeName, 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 b4b3a37222..15a4e1520d 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 @@ -418,6 +418,8 @@ internal class DataSource private const string LocalDbHost_NP = @"np:\\.\pipe\LOCALDB#"; private const string NamedPipeInstanceNameHeader = "mssql$"; private const string DefaultPipeName = "sql\\query"; + private const string InstancePrefix = "MSSQL$"; + private const string PathSeparator = "\\"; internal enum Protocol { TCP, NP, None, Admin }; @@ -676,12 +678,35 @@ private bool InferNamedPipesInformation() // If we have a datasource beginning with a pipe or we have already determined that the protocol is Named Pipe if (_dataSourceAfterTrimmingProtocol.StartsWith(PipeBeginning, StringComparison.Ordinal) || _connectionProtocol == Protocol.NP) { - // If the data source is "np:servername" + // If the data source starts with "np:servername" if (!_dataSourceAfterTrimmingProtocol.Contains(PipeBeginning)) { - PipeHostName = ServerName = _dataSourceAfterTrimmingProtocol; + // Assuming that user did not change default NamedPipe name, if the datasource is in the format servername\instance, + // separate servername and instance and prepend instance with MSSQL$ and append default pipe path + // https://learn.microsoft.com/en-us/sql/tools/configuration-manager/named-pipes-properties?view=sql-server-ver16 + if (_dataSourceAfterTrimmingProtocol.Contains(PathSeparator) && _connectionProtocol == Protocol.NP) + { + string[] tokensByBackSlash = _dataSourceAfterTrimmingProtocol.Split(BackSlashCharacter); + if (tokensByBackSlash.Length == 2) + { + // NamedPipeClientStream object will create the network path using PipeHostName and PipeName + // and can be seen in its _normalizedPipePath variable in the format \\servername\pipe\MSSQL$\sql\query + PipeHostName = ServerName = tokensByBackSlash[0]; + PipeName = $"{InstancePrefix}{tokensByBackSlash[1]}{PathSeparator}{DefaultPipeName}"; + } + else + { + ReportSNIError(SNIProviders.NP_PROV); + return false; + } + } + else + { + PipeHostName = ServerName = _dataSourceAfterTrimmingProtocol; + PipeName = SNINpHandle.DefaultPipePath; + } + InferLocalServerName(); - PipeName = SNINpHandle.DefaultPipePath; return true; } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/InstanceNameTest/InstanceNameTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/InstanceNameTest/InstanceNameTest.cs index 1ae87217b6..311ce5fce5 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/InstanceNameTest/InstanceNameTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/InstanceNameTest/InstanceNameTest.cs @@ -76,7 +76,7 @@ public static void ConnectManagedWithInstanceNameTest(bool useMultiSubnetFailove if (!IsValidInstance(hostname, instanceName)) { builder.DataSource = hostname + "\\" + instanceName; - + using SqlConnection connection = new(builder.ConnectionString); SqlException ex = Assert.Throws(() => connection.Open()); Assert.Contains("Error Locating Server/Instance Specified", ex.Message); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCredentialTest/SqlCredentialTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCredentialTest/SqlCredentialTest.cs index c3d290c09a..ae656f11a4 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCredentialTest/SqlCredentialTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCredentialTest/SqlCredentialTest.cs @@ -12,7 +12,6 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests { public static class SqlCredentialTest { - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] public static void CreateSqlConnectionWithCredential() {