Skip to content

Commit

Permalink
Fix Transient fault handling issue with OpenAsync (dotnet#1983)
Browse files Browse the repository at this point in the history
  • Loading branch information
cheenamalhotra authored and kant2002 committed Jun 29, 2023
1 parent 5c4b007 commit 9bb215c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 8 deletions.
Expand Up @@ -1856,7 +1856,7 @@ private bool TryOpen(TaskCompletionSource<DbConnectionInternal> retry, SqlConnec
}
}

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

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

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

var tdsInnerConnection = (SqlInternalConnectionTds)InnerConnection;

Expand Down
Expand Up @@ -2068,7 +2068,7 @@ private bool TryOpen(TaskCompletionSource<DbConnectionInternal> retry, SqlConnec

bool result = false;

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

if (connectionOptions != null &&
(connectionOptions.Authentication == SqlAuthenticationMethod.SqlPassword ||
Expand Down Expand Up @@ -2111,7 +2111,7 @@ private bool TryOpen(TaskCompletionSource<DbConnectionInternal> retry, SqlConnec
}

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

return result;
}
Expand Down
Expand Up @@ -7,6 +7,7 @@
using System.Data.Common;
using System.Reflection;
using System.Security;
using System.Threading.Tasks;
using Microsoft.SqlServer.TDS.Servers;
using Xunit;

Expand Down Expand Up @@ -34,6 +35,26 @@ public void IntegratedAuthConnectionTest()
connection.Open();
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))]
[InlineData(40613)]
[InlineData(42108)]
[InlineData(42109)]
[PlatformSpecific(TestPlatforms.Windows)]
public async Task TransientFaultTestAsync(uint errorCode)
{
using TransientFaultTDSServer server = TransientFaultTDSServer.StartTestServer(true, true, errorCode);
SqlConnectionStringBuilder builder = new()
{
DataSource = "localhost," + server.Port,
IntegratedSecurity = true,
Encrypt = SqlConnectionEncryptOption.Optional
};

using SqlConnection connection = new(builder.ConnectionString);
await connection.OpenAsync();
Assert.Equal(ConnectionState.Open, connection.State);
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))]
[InlineData(40613)]
[InlineData(42108)]
Expand All @@ -57,14 +78,70 @@ public void TransientFaultTest(uint errorCode)
}
catch (Exception e)
{
if (null != connection)
{
Assert.Equal(ConnectionState.Closed, connection.State);
}
Assert.False(true, e.Message);
}
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))]
[InlineData(40613)]
[InlineData(42108)]
[InlineData(42109)]
[PlatformSpecific(TestPlatforms.Windows)]
public async Task TransientFaultDisabledTestAsync(uint errorCode)
{
using TransientFaultTDSServer server = TransientFaultTDSServer.StartTestServer(true, true, errorCode);
SqlConnectionStringBuilder builder = new()
{
DataSource = "localhost," + server.Port,
IntegratedSecurity = true,
ConnectRetryCount = 0,
Encrypt = SqlConnectionEncryptOption.Optional
};

using SqlConnection connection = new(builder.ConnectionString);
try
{
await connection.OpenAsync();
Assert.False(true, "Connection should not have opened.");
}
catch (SqlException e)
{
// FATAL Error, should result in closed connection.
Assert.Equal(20, e.Class);
Assert.Equal(ConnectionState.Closed, connection.State);
}
}

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))]
[InlineData(40613)]
[InlineData(42108)]
[InlineData(42109)]
[PlatformSpecific(TestPlatforms.Windows)]
public void TransientFaultDisabledTest(uint errorCode)
{
using TransientFaultTDSServer server = TransientFaultTDSServer.StartTestServer(true, true, errorCode);
SqlConnectionStringBuilder builder = new()
{
DataSource = "localhost," + server.Port,
IntegratedSecurity = true,
ConnectRetryCount = 0,
Encrypt = SqlConnectionEncryptOption.Optional
};

using SqlConnection connection = new(builder.ConnectionString);
try
{
connection.Open();
Assert.False(true, "Connection should not have opened.");
}
catch (SqlException e)
{
// FATAL Error, should result in closed connection.
Assert.Equal(20, e.Class);
Assert.Equal(ConnectionState.Closed, connection.State);
}
}

[Fact]
public void SqlConnectionDbProviderFactoryTest()
{
Expand Down
Expand Up @@ -146,6 +146,7 @@ private void Dispose(bool isDisposing)
if (isDisposing)
{
_endpoint?.Stop();
RequestCounter = 0;
}
}
}
Expand Down

0 comments on commit 9bb215c

Please sign in to comment.