Skip to content

Commit 80d1f47

Browse files
Merged PR 4035: [5.1.2] | Fix Transient fault handling issue with OpenAsync (dotnet#1983)
Ports [dotnet#1983](dotnet#1983)
1 parent 39cedc8 commit 80d1f47

File tree

4 files changed

+86
-8
lines changed

4 files changed

+86
-8
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,7 +1820,7 @@ private bool TryOpen(TaskCompletionSource<DbConnectionInternal> retry, SqlConnec
18201820
}
18211821
}
18221822

1823-
_applyTransientFaultHandling = (!overrides.HasFlag(SqlConnectionOverrides.OpenWithoutRetry) && retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);
1823+
_applyTransientFaultHandling = (!overrides.HasFlag(SqlConnectionOverrides.OpenWithoutRetry) && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);
18241824

18251825
if (connectionOptions != null &&
18261826
(connectionOptions.Authentication == SqlAuthenticationMethod.SqlPassword ||
@@ -1849,7 +1849,7 @@ private bool TryOpen(TaskCompletionSource<DbConnectionInternal> retry, SqlConnec
18491849
// does not require GC.KeepAlive(this) because of ReRegisterForFinalize below.
18501850

18511851
// Set future transient fault handling based on connection options
1852-
_applyTransientFaultHandling = (retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);
1852+
_applyTransientFaultHandling = connectionOptions != null && connectionOptions.ConnectRetryCount > 0;
18531853

18541854
var tdsInnerConnection = (SqlInternalConnectionTds)InnerConnection;
18551855

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2059,7 +2059,7 @@ private bool TryOpen(TaskCompletionSource<DbConnectionInternal> retry, SqlConnec
20592059

20602060
bool result = false;
20612061

2062-
_applyTransientFaultHandling = (!overrides.HasFlag(SqlConnectionOverrides.OpenWithoutRetry) && retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);
2062+
_applyTransientFaultHandling = (!overrides.HasFlag(SqlConnectionOverrides.OpenWithoutRetry) && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);
20632063

20642064
if (connectionOptions != null &&
20652065
(connectionOptions.Authentication == SqlAuthenticationMethod.SqlPassword ||
@@ -2102,7 +2102,7 @@ private bool TryOpen(TaskCompletionSource<DbConnectionInternal> retry, SqlConnec
21022102
}
21032103

21042104
// Set future transient fault handling based on connection options
2105-
_applyTransientFaultHandling = (retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);
2105+
_applyTransientFaultHandling = connectionOptions != null && connectionOptions.ConnectRetryCount > 0;
21062106

21072107
return result;
21082108
}

src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Data.Common;
88
using System.Reflection;
99
using System.Security;
10+
using System.Threading.Tasks;
1011
using Microsoft.SqlServer.TDS.Servers;
1112
using Xunit;
1213

@@ -34,6 +35,26 @@ public void IntegratedAuthConnectionTest()
3435
connection.Open();
3536
}
3637

38+
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))]
39+
[InlineData(40613)]
40+
[InlineData(42108)]
41+
[InlineData(42109)]
42+
[PlatformSpecific(TestPlatforms.Windows)]
43+
public async Task TransientFaultTestAsync(uint errorCode)
44+
{
45+
using TransientFaultTDSServer server = TransientFaultTDSServer.StartTestServer(true, true, errorCode);
46+
SqlConnectionStringBuilder builder = new()
47+
{
48+
DataSource = "localhost," + server.Port,
49+
IntegratedSecurity = true,
50+
Encrypt = SqlConnectionEncryptOption.Optional
51+
};
52+
53+
using SqlConnection connection = new(builder.ConnectionString);
54+
await connection.OpenAsync();
55+
Assert.Equal(ConnectionState.Open, connection.State);
56+
}
57+
3758
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))]
3859
[InlineData(40613)]
3960
[InlineData(42108)]
@@ -57,14 +78,70 @@ public void TransientFaultTest(uint errorCode)
5778
}
5879
catch (Exception e)
5980
{
60-
if (null != connection)
61-
{
62-
Assert.Equal(ConnectionState.Closed, connection.State);
63-
}
6481
Assert.False(true, e.Message);
6582
}
6683
}
6784

85+
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))]
86+
[InlineData(40613)]
87+
[InlineData(42108)]
88+
[InlineData(42109)]
89+
[PlatformSpecific(TestPlatforms.Windows)]
90+
public async Task TransientFaultDisabledTestAsync(uint errorCode)
91+
{
92+
using TransientFaultTDSServer server = TransientFaultTDSServer.StartTestServer(true, true, errorCode);
93+
SqlConnectionStringBuilder builder = new()
94+
{
95+
DataSource = "localhost," + server.Port,
96+
IntegratedSecurity = true,
97+
ConnectRetryCount = 0,
98+
Encrypt = SqlConnectionEncryptOption.Optional
99+
};
100+
101+
using SqlConnection connection = new(builder.ConnectionString);
102+
try
103+
{
104+
await connection.OpenAsync();
105+
Assert.False(true, "Connection should not have opened.");
106+
}
107+
catch (SqlException e)
108+
{
109+
// FATAL Error, should result in closed connection.
110+
Assert.Equal(20, e.Class);
111+
Assert.Equal(ConnectionState.Closed, connection.State);
112+
}
113+
}
114+
115+
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))]
116+
[InlineData(40613)]
117+
[InlineData(42108)]
118+
[InlineData(42109)]
119+
[PlatformSpecific(TestPlatforms.Windows)]
120+
public void TransientFaultDisabledTest(uint errorCode)
121+
{
122+
using TransientFaultTDSServer server = TransientFaultTDSServer.StartTestServer(true, true, errorCode);
123+
SqlConnectionStringBuilder builder = new()
124+
{
125+
DataSource = "localhost," + server.Port,
126+
IntegratedSecurity = true,
127+
ConnectRetryCount = 0,
128+
Encrypt = SqlConnectionEncryptOption.Optional
129+
};
130+
131+
using SqlConnection connection = new(builder.ConnectionString);
132+
try
133+
{
134+
connection.Open();
135+
Assert.False(true, "Connection should not have opened.");
136+
}
137+
catch (SqlException e)
138+
{
139+
// FATAL Error, should result in closed connection.
140+
Assert.Equal(20, e.Class);
141+
Assert.Equal(ConnectionState.Closed, connection.State);
142+
}
143+
}
144+
68145
[Fact]
69146
public void SqlConnectionDbProviderFactoryTest()
70147
{

src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TransientFaultTDSServer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ private void Dispose(bool isDisposing)
146146
if (isDisposing)
147147
{
148148
_endpoint?.Stop();
149+
RequestCounter = 0;
149150
}
150151
}
151152
}

0 commit comments

Comments
 (0)