Skip to content

Commit a43348b

Browse files
authored
Automatically adjust the default ConnectRetryCount if targeting OnDemand endpoint (#1626)
1 parent 2cfac4d commit a43348b

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -412,9 +412,15 @@ private void CacheConnectionStringProperties()
412412
if (connString != null)
413413
{
414414
_connectRetryCount = connString.ConnectRetryCount;
415+
// For Azure Synapse ondemand connections, set _connectRetryCount to 5 instead of 1 to greatly improve recovery
416+
// success rate. Note: Synapse should be detected first as it could be detected as a regular Azure SQL DB endpoint.
417+
if (_connectRetryCount == 1 && ADP.IsAzureSynapseOnDemandEndpoint(connString.DataSource))
418+
{
419+
_connectRetryCount = 5;
420+
}
415421
// For Azure SQL connection, set _connectRetryCount to 2 instead of 1 will greatly improve recovery
416-
// success rate
417-
if (_connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connString.DataSource))
422+
// success rate
423+
else if (_connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connString.DataSource))
418424
{
419425
_connectRetryCount = 2;
420426
}

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,15 @@ private void CacheConnectionStringProperties()
432432
if (connString != null)
433433
{
434434
_connectRetryCount = connString.ConnectRetryCount;
435+
// For Azure Synapse ondemand connections, set _connectRetryCount to 5 instead of 1 to greatly improve recovery
436+
// success rate. Note: Synapse should be detected first as it could be detected as a regular Azure SQL DB endpoint.
437+
if (_connectRetryCount == 1 && ADP.IsAzureSynapseOnDemandEndpoint(connString.DataSource))
438+
{
439+
_connectRetryCount = 5;
440+
}
435441
// For Azure SQL connection, set _connectRetryCount to 2 instead of 1 will greatly improve recovery
436-
// success rate
437-
if (_connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connString.DataSource))
442+
// success rate
443+
else if (_connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connString.DataSource))
438444
{
439445
_connectRetryCount = 2;
440446
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs

+16-3
Original file line numberDiff line numberDiff line change
@@ -686,13 +686,26 @@ internal static Version GetAssemblyVersion()
686686
}
687687

688688

689+
private const string ONDEMAND_PREFIX = "-ondemand";
690+
private const string AZURE_SYNAPSE = "-ondemand.sql.azuresynapse.";
691+
692+
internal static bool IsAzureSynapseOnDemandEndpoint(string dataSource)
693+
{
694+
return IsEndpoint(dataSource, ONDEMAND_PREFIX) || dataSource.Contains(AZURE_SYNAPSE);
695+
}
696+
689697
internal static readonly string[] s_azureSqlServerEndpoints = { StringsHelper.GetString(Strings.AZURESQL_GenericEndpoint),
690698
StringsHelper.GetString(Strings.AZURESQL_GermanEndpoint),
691699
StringsHelper.GetString(Strings.AZURESQL_UsGovEndpoint),
692700
StringsHelper.GetString(Strings.AZURESQL_ChinaEndpoint)};
693701

694-
// This method assumes dataSource parameter is in TCP connection string format.
695702
internal static bool IsAzureSqlServerEndpoint(string dataSource)
703+
{
704+
return IsEndpoint(dataSource, null);
705+
}
706+
707+
// This method assumes dataSource parameter is in TCP connection string format.
708+
private static bool IsEndpoint(string dataSource, string prefix)
696709
{
697710
int length = dataSource.Length;
698711
// remove server port
@@ -715,10 +728,10 @@ internal static bool IsAzureSqlServerEndpoint(string dataSource)
715728
length -= 1;
716729
}
717730

718-
// check if servername end with any azure endpoints
731+
// check if servername ends with any endpoints
719732
for (int index = 0; index < s_azureSqlServerEndpoints.Length; index++)
720733
{
721-
string endpoint = s_azureSqlServerEndpoints[index];
734+
string endpoint = string.IsNullOrEmpty(prefix) ? s_azureSqlServerEndpoints[index] : prefix + s_azureSqlServerEndpoints[index];
722735
if (length > endpoint.Length)
723736
{
724737
if (string.Compare(dataSource, length - endpoint.Length, endpoint, 0, endpoint.Length, StringComparison.OrdinalIgnoreCase) == 0)

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

+30
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Data;
77
using System.Collections.Generic;
88
using Xunit;
9+
using System.Reflection;
910

1011
namespace Microsoft.Data.SqlClient.Tests
1112
{
@@ -1031,5 +1032,34 @@ public void ConnectionString_IPAddressPreference_Invalid(string value)
10311032
Assert.Contains("'ip address preference'", ex.Message, StringComparison.OrdinalIgnoreCase);
10321033
Assert.Null(ex.ParamName);
10331034
}
1035+
1036+
[Fact]
1037+
public void ConnectionRetryForNonAzureEndpoints()
1038+
{
1039+
SqlConnection cn = new SqlConnection("Data Source = someserver");
1040+
FieldInfo field = typeof(SqlConnection).GetField("_connectRetryCount", BindingFlags.Instance | BindingFlags.NonPublic);
1041+
Assert.NotNull(field.GetValue(cn));
1042+
Assert.Equal(1, (int)field.GetValue(cn));
1043+
}
1044+
1045+
[Fact]
1046+
public void ConnectionRetryForAzureDbEndpoints()
1047+
{
1048+
SqlConnection cn = new SqlConnection("Data Source = someserver.database.windows.net");
1049+
FieldInfo field = typeof(SqlConnection).GetField("_connectRetryCount", BindingFlags.Instance | BindingFlags.NonPublic);
1050+
Assert.NotNull(field.GetValue(cn));
1051+
Assert.Equal(2, (int)field.GetValue(cn));
1052+
}
1053+
1054+
[Theory]
1055+
[InlineData("myserver-ondemand.sql.azuresynapse.net")]
1056+
[InlineData("someserver-ondemand.database.windows.net")]
1057+
public void ConnectionRetryForAzureOnDemandEndpoints(string serverName)
1058+
{
1059+
SqlConnection cn = new SqlConnection($"Data Source = {serverName}");
1060+
FieldInfo field = typeof(SqlConnection).GetField("_connectRetryCount", BindingFlags.Instance | BindingFlags.NonPublic);
1061+
Assert.NotNull(field.GetValue(cn));
1062+
Assert.Equal(5, (int)field.GetValue(cn));
1063+
}
10341064
}
10351065
}

0 commit comments

Comments
 (0)