From 451e95aab11b54b8b3bd18dd5be4f7bdef764418 Mon Sep 17 00:00:00 2001 From: JRahnama Date: Thu, 5 Jan 2023 16:15:48 -0800 Subject: [PATCH 1/8] addressing named pipe issue. --- .../Data/SqlClient/SNI/SNINpHandle.cs | 6 +++- .../SqlConnectionReliabilityTest.cs | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) 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 b48ea36958..5b1b044440 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 @@ -48,11 +48,15 @@ public SNINpHandle(string serverName, string pipeName, long timerExpire, bool tl _tlsFirst = tlsFirst; try { + // we either have to pass a variable indicating if the process is async and add some thing like below or take the PipeOptions.Asynchronous totally out. This PR is going with the second approach. I have tested with the first one, but the + // value for async in TDSParser is set to be always true and I am not sure about the reasoning and needs more investigations to see the outcome of changing that value in the entire driver aspect. + //PipeOptions options = _async? PipeOptions.Asynchronous | PipeOptions.WriteThrough : PipeOptions.WriteThrough + _pipeStream = new NamedPipeClientStream( serverName, pipeName, PipeDirection.InOut, - PipeOptions.Asynchronous | PipeOptions.WriteThrough); + PipeOptions.WriteThrough); bool isInfiniteTimeOut = long.MaxValue == timerExpire; if (isInfiniteTimeOut) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs index 624912f260..1aea785935 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs @@ -130,6 +130,41 @@ public void ConcurrentExecution(string cnnString, SqlRetryLogicBaseProvider prov Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); } +#if NETCOREAPP + + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] + public async Task ConcurrentExecutionAsync(string cnnString, SqlRetryLogicBaseProvider provider) + { + int numberOfTries = provider.RetryLogic.NumberOfTries; + int cancelAfterRetries = numberOfTries + 1; + int retriesCount = 0; + int concurrentExecution = 5; + provider.Retrying += (s, e) => Interlocked.Increment(ref retriesCount); + + await Parallel.ForEachAsync(System.Linq.Enumerable.Range(0, concurrentExecution), + async (i, c) => + { + using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) + { + await Assert.ThrowsAsync(async () => await cnn.OpenAsync()); + } + }); + Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); + + retriesCount = 0; + Parallel.For(0, concurrentExecution, + i => + { + using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) + { + Assert.ThrowsAsync(() => cnn.OpenAsync()).Wait(); + } + }); + Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); + } +#endif + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] [MemberData(nameof(RetryLogicTestHelper.GetNoneRetriableCondition), MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void DefaultOpenWithoutRetry(string connectionString, SqlRetryLogicBaseProvider cnnProvider) From 2df8e7e50c9d92030026deb380a07e610aebf19c Mon Sep 17 00:00:00 2001 From: JRahnama Date: Fri, 6 Jan 2023 04:40:25 -0800 Subject: [PATCH 2/8] trigger pipeline --- .../netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 5b1b044440..d85a9fa698 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 @@ -48,8 +48,9 @@ public SNINpHandle(string serverName, string pipeName, long timerExpire, bool tl _tlsFirst = tlsFirst; try { - // we either have to pass a variable indicating if the process is async and add some thing like below or take the PipeOptions.Asynchronous totally out. This PR is going with the second approach. I have tested with the first one, but the - // value for async in TDSParser is set to be always true and I am not sure about the reasoning and needs more investigations to see the outcome of changing that value in the entire driver aspect. + // we either have to pass a variable indicating if the process is async and add some thing like below or take the PipeOptions.Asynchronous totally out. This PR is going with the second approach. + // I have tested with the first one, but the value for async in TDSParser is set to be always true and I am not sure about the reasoning and needs more investigations to see the outcome of changing that value in + // the entire driver aspect. //PipeOptions options = _async? PipeOptions.Asynchronous | PipeOptions.WriteThrough : PipeOptions.WriteThrough _pipeStream = new NamedPipeClientStream( From 121182a7b7695c5fb9d2dc597112de0758cda5a9 Mon Sep 17 00:00:00 2001 From: JRahnama Date: Fri, 6 Jan 2023 13:58:25 -0800 Subject: [PATCH 3/8] rerun pipelines --- .../netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs | 1 + 1 file changed, 1 insertion(+) 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 d85a9fa698..2d6a32c8f5 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 @@ -51,6 +51,7 @@ public SNINpHandle(string serverName, string pipeName, long timerExpire, bool tl // we either have to pass a variable indicating if the process is async and add some thing like below or take the PipeOptions.Asynchronous totally out. This PR is going with the second approach. // I have tested with the first one, but the value for async in TDSParser is set to be always true and I am not sure about the reasoning and needs more investigations to see the outcome of changing that value in // the entire driver aspect. + // //PipeOptions options = _async? PipeOptions.Asynchronous | PipeOptions.WriteThrough : PipeOptions.WriteThrough _pipeStream = new NamedPipeClientStream( From 4b53af6a2a9077d55a380490bfebe01760525b60 Mon Sep 17 00:00:00 2001 From: JRahnama Date: Fri, 6 Jan 2023 14:53:45 -0800 Subject: [PATCH 4/8] commit --- .../SqlConnectionReliabilityTest.cs | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs index 1aea785935..ac0856b9cf 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs @@ -130,40 +130,40 @@ public void ConcurrentExecution(string cnnString, SqlRetryLogicBaseProvider prov Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); } -#if NETCOREAPP - - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] - public async Task ConcurrentExecutionAsync(string cnnString, SqlRetryLogicBaseProvider provider) - { - int numberOfTries = provider.RetryLogic.NumberOfTries; - int cancelAfterRetries = numberOfTries + 1; - int retriesCount = 0; - int concurrentExecution = 5; - provider.Retrying += (s, e) => Interlocked.Increment(ref retriesCount); - - await Parallel.ForEachAsync(System.Linq.Enumerable.Range(0, concurrentExecution), - async (i, c) => - { - using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) - { - await Assert.ThrowsAsync(async () => await cnn.OpenAsync()); - } - }); - Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); - - retriesCount = 0; - Parallel.For(0, concurrentExecution, - i => - { - using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) - { - Assert.ThrowsAsync(() => cnn.OpenAsync()).Wait(); - } - }); - Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); - } -#endif +//#if NETCOREAPP + +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] +// public async Task ConcurrentExecutionAsync(string cnnString, SqlRetryLogicBaseProvider provider) +// { +// int numberOfTries = provider.RetryLogic.NumberOfTries; +// int cancelAfterRetries = numberOfTries + 1; +// int retriesCount = 0; +// int concurrentExecution = 5; +// provider.Retrying += (s, e) => Interlocked.Increment(ref retriesCount); + +// await Parallel.ForEachAsync(System.Linq.Enumerable.Range(0, concurrentExecution), +// async (i, c) => +// { +// using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) +// { +// await Assert.ThrowsAsync(async () => await cnn.OpenAsync()); +// } +// }); +// Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); + +// retriesCount = 0; +// Parallel.For(0, concurrentExecution, +// i => +// { +// using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) +// { +// Assert.ThrowsAsync(() => cnn.OpenAsync()).Wait(); +// } +// }); +// Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); +// } +//#endif [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] [MemberData(nameof(RetryLogicTestHelper.GetNoneRetriableCondition), MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] From dd9e441f67e5374f15055de30c44eb1f65e1edf4 Mon Sep 17 00:00:00 2001 From: JRahnama Date: Fri, 27 Jan 2023 15:26:32 -0800 Subject: [PATCH 5/8] commit --- .../netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2d6a32c8f5..0f42f9a7ed 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 @@ -58,7 +58,7 @@ public SNINpHandle(string serverName, string pipeName, long timerExpire, bool tl serverName, pipeName, PipeDirection.InOut, - PipeOptions.WriteThrough); + PipeOptions.WriteThrough); // test without async option bool isInfiniteTimeOut = long.MaxValue == timerExpire; if (isInfiniteTimeOut) From c5cf36379b93c760a918c94955c2d241444f5647 Mon Sep 17 00:00:00 2001 From: "H. Yeo" <138053434+H-Yeo@users.noreply.github.com> Date: Thu, 7 Dec 2023 09:05:56 -0800 Subject: [PATCH 6/8] Configuration Prep for Async PipeOptions - Setup Parameterization so PipeOptions can be configured for Async or WriteThrough --- .../src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs | 10 +++------- .../src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs | 7 ++++--- .../src/Microsoft/Data/SqlClient/SqlConnection.cs | 1 + .../netcore/src/Microsoft/Data/SqlClient/TdsParser.cs | 7 ++++--- 4 files changed, 12 insertions(+), 13 deletions(-) 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 0f42f9a7ed..0f40a70df7 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 @@ -37,7 +37,7 @@ internal sealed class SNINpHandle : SNIPhysicalHandle private int _bufferSize = TdsEnums.DEFAULT_LOGIN_PACKET_SIZE; private readonly Guid _connectionId = Guid.NewGuid(); - public SNINpHandle(string serverName, string pipeName, long timerExpire, bool tlsFirst) + public SNINpHandle(string serverName, string pipeName, long timerExpire, bool tlsFirst, bool isAsyncOption) { using (TrySNIEventScope.Create(nameof(SNINpHandle))) { @@ -48,17 +48,13 @@ public SNINpHandle(string serverName, string pipeName, long timerExpire, bool tl _tlsFirst = tlsFirst; try { - // we either have to pass a variable indicating if the process is async and add some thing like below or take the PipeOptions.Asynchronous totally out. This PR is going with the second approach. - // I have tested with the first one, but the value for async in TDSParser is set to be always true and I am not sure about the reasoning and needs more investigations to see the outcome of changing that value in - // the entire driver aspect. - // - //PipeOptions options = _async? PipeOptions.Asynchronous | PipeOptions.WriteThrough : PipeOptions.WriteThrough + PipeOptions pipeOptions = isAsyncOption ? PipeOptions.Asynchronous | PipeOptions.WriteThrough : PipeOptions.WriteThrough; _pipeStream = new NamedPipeClientStream( serverName, pipeName, PipeDirection.InOut, - PipeOptions.WriteThrough); // test without async option + pipeOptions); bool isInfiniteTimeOut = long.MaxValue == timerExpire; if (isInfiniteTimeOut) 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 ac4d3599dd..7a1d1083e1 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 @@ -192,7 +192,7 @@ internal static SNIHandle CreateConnectionHandle( tlsFirst, hostNameInCertificate, serverCertificateFilename); break; case DataSource.Protocol.NP: - sniHandle = CreateNpHandle(details, timerExpire, parallel, tlsFirst); + sniHandle = CreateNpHandle(details, timerExpire, parallel, tlsFirst, isAsyncOption : async); break; default: Debug.Fail($"Unexpected connection protocol: {details._connectionProtocol}"); @@ -348,8 +348,9 @@ private static SNITCPHandle CreateTcpHandle( /// Timer expiration /// Should MultiSubnetFailover be used. Only returns an error for named pipes. /// + /// /// SNINpHandle - private static SNINpHandle CreateNpHandle(DataSource details, long timerExpire, bool parallel, bool tlsFirst) + private static SNINpHandle CreateNpHandle(DataSource details, long timerExpire, bool parallel, bool tlsFirst, bool isAsyncOption) { if (parallel) { @@ -357,7 +358,7 @@ private static SNINpHandle CreateNpHandle(DataSource details, long timerExpire, SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.MultiSubnetFailoverWithNonTcpProtocol, Strings.SNI_ERROR_49); return null; } - return new SNINpHandle(details.PipeHostName, details.PipeName, timerExpire, tlsFirst); + return new SNINpHandle(details.PipeHostName, details.PipeName, timerExpire, tlsFirst, isAsyncOption); } /// 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 660b5934e0..dcc30374bc 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 @@ -1589,6 +1589,7 @@ private Task InternalOpenAsync(CancellationToken cancellationToken) { long scopeID = SqlClientEventSource.Log.TryPoolerScopeEnterEvent("SqlConnection.InternalOpenAsync | API | Object Id {0}", ObjectID); SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlConnection.InternalOpenAsync | API | Correlation | Object Id {0}, Activity Id {1}", ObjectID, ActivityCorrelator.Current); + try { Guid operationId = s_diagnosticListener.WriteConnectionOpenBefore(this); 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 8217604c72..31513b3609 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 @@ -450,7 +450,7 @@ internal void Connect( out instanceName, ref _sniSpnBuffer, false, - true, + async: true, fParallel, _connHandler.ConnectionOptions.IPAddressPreference, FQDNforDNSCache, @@ -545,10 +545,11 @@ internal void Connect( _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, ignoreSniOpenTimeout, - timerExpire, out instanceName, + timerExpire, + out instanceName, ref _sniSpnBuffer, true, - true, + async: true, fParallel, _connHandler.ConnectionOptions.IPAddressPreference, FQDNforDNSCache, From db3e726e5540f2f0c28a0bcfb450bfef1e6bc6bc Mon Sep 17 00:00:00 2001 From: "H. Yeo" <138053434+H-Yeo@users.noreply.github.com> Date: Thu, 7 Dec 2023 12:51:46 -0800 Subject: [PATCH 7/8] Change Variable Name Change to a more precise variable name --- .../Microsoft/Data/SqlClient/SqlConnection.cs | 7 ++ .../src/Microsoft/Data/SqlClient/TdsParser.cs | 1 + .../SqlConnectionReliabilityTest.cs | 68 +++++++++---------- 3 files changed, 42 insertions(+), 34 deletions(-) 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 dcc30374bc..5f6427aa25 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 @@ -38,6 +38,7 @@ private enum CultureCheckState : uint } private bool _AsyncCommandInProgress; + private bool _isAsyncPipeOption = false; // SQLStatistics support internal SqlStatistics _statistics; @@ -496,6 +497,11 @@ internal bool AsyncCommandInProgress set => _AsyncCommandInProgress = value; } + internal bool IsAsyncPipeOption + { + get => _isAsyncPipeOption; + } + private bool UsesActiveDirectoryIntegrated(SqlConnectionString opt) { return opt != null && opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated; @@ -1589,6 +1595,7 @@ private Task InternalOpenAsync(CancellationToken cancellationToken) { long scopeID = SqlClientEventSource.Log.TryPoolerScopeEnterEvent("SqlConnection.InternalOpenAsync | API | Object Id {0}", ObjectID); SqlClientEventSource.Log.TryCorrelationTraceEvent("SqlConnection.InternalOpenAsync | API | Correlation | Object Id {0}, Activity Id {1}", ObjectID, ActivityCorrelator.Current); + _isAsyncPipeOption = true; try { 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 31513b3609..a1692e9868 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 @@ -443,6 +443,7 @@ internal void Connect( _connHandler.pendingSQLDNSObject = null; // AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server + _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, ignoreSniOpenTimeout, diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs index ac0856b9cf..1aea785935 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs @@ -130,40 +130,40 @@ public void ConcurrentExecution(string cnnString, SqlRetryLogicBaseProvider prov Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); } -//#if NETCOREAPP - -// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] -// [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] -// public async Task ConcurrentExecutionAsync(string cnnString, SqlRetryLogicBaseProvider provider) -// { -// int numberOfTries = provider.RetryLogic.NumberOfTries; -// int cancelAfterRetries = numberOfTries + 1; -// int retriesCount = 0; -// int concurrentExecution = 5; -// provider.Retrying += (s, e) => Interlocked.Increment(ref retriesCount); - -// await Parallel.ForEachAsync(System.Linq.Enumerable.Range(0, concurrentExecution), -// async (i, c) => -// { -// using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) -// { -// await Assert.ThrowsAsync(async () => await cnn.OpenAsync()); -// } -// }); -// Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); - -// retriesCount = 0; -// Parallel.For(0, concurrentExecution, -// i => -// { -// using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) -// { -// Assert.ThrowsAsync(() => cnn.OpenAsync()).Wait(); -// } -// }); -// Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); -// } -//#endif +#if NETCOREAPP + + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] + public async Task ConcurrentExecutionAsync(string cnnString, SqlRetryLogicBaseProvider provider) + { + int numberOfTries = provider.RetryLogic.NumberOfTries; + int cancelAfterRetries = numberOfTries + 1; + int retriesCount = 0; + int concurrentExecution = 5; + provider.Retrying += (s, e) => Interlocked.Increment(ref retriesCount); + + await Parallel.ForEachAsync(System.Linq.Enumerable.Range(0, concurrentExecution), + async (i, c) => + { + using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) + { + await Assert.ThrowsAsync(async () => await cnn.OpenAsync()); + } + }); + Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); + + retriesCount = 0; + Parallel.For(0, concurrentExecution, + i => + { + using (var cnn = CreateConnectionWithInvalidCatalog(cnnString, provider, cancelAfterRetries)) + { + Assert.ThrowsAsync(() => cnn.OpenAsync()).Wait(); + } + }); + Assert.Equal(numberOfTries * concurrentExecution, retriesCount + concurrentExecution); + } +#endif [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] [MemberData(nameof(RetryLogicTestHelper.GetNoneRetriableCondition), MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] From 71054c02ae9179f54037b50ec4a4e19394bb1ae1 Mon Sep 17 00:00:00 2001 From: "H. Yeo" <138053434+H-Yeo@users.noreply.github.com> Date: Fri, 8 Dec 2023 10:08:21 -0800 Subject: [PATCH 8/8] Add SqlConnection Async to TDS Add the setting of the Asynchronous Variable assignment to SqlInternalConnectionTds --- .../Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs | 3 ++- .../netcore/src/Microsoft/Data/SqlClient/TdsParser.cs | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) 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 e977641175..4e0035f020 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 @@ -1911,7 +1911,8 @@ private void AttemptOneLogin( ignoreSniOpenTimeout, timeout.LegacyTimerExpire, ConnectionOptions, - withFailover); + withFailover, + Connection.IsAsyncPipeOption); _timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake); _timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.LoginBegin); 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 a1692e9868..913377adea 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 @@ -364,7 +364,8 @@ internal void Connect( bool ignoreSniOpenTimeout, long timerExpire, SqlConnectionString connectionOptions, - bool withFailover) + bool withFailover, + bool isAsyncPipeOption) { SqlConnectionEncryptOption encrypt = connectionOptions.Encrypt; bool isTlsFirst = (encrypt == SqlConnectionEncryptOption.Strict); @@ -451,7 +452,7 @@ internal void Connect( out instanceName, ref _sniSpnBuffer, false, - async: true, + async: isAsyncPipeOption, fParallel, _connHandler.ConnectionOptions.IPAddressPreference, FQDNforDNSCache, @@ -550,7 +551,7 @@ internal void Connect( out instanceName, ref _sniSpnBuffer, true, - async: true, + async: isAsyncPipeOption, fParallel, _connHandler.ConnectionOptions.IPAddressPreference, FQDNforDNSCache,