Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal static class DbConnectionStringDefaults
internal const int MaxPoolSize = 100;
internal const int MinPoolSize = 0;
internal const bool MultipleActiveResultSets = false;
internal const bool MultiSubnetFailover = false;
internal static bool MultiSubnetFailover => LocalAppContextSwitches.EnableMultiSubnetFailoverByDefault;
internal const int PacketSize = 8000;
internal const string Password = "";
internal const bool PersistSecurityInfo = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ private enum Tristate : byte
private const string TruncateScaledDecimalString = @"Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal";
private const string IgnoreServerProvidedFailoverPartnerString = @"Switch.Microsoft.Data.SqlClient.IgnoreServerProvidedFailoverPartner";
private const string EnableUserAgentString = @"Switch.Microsoft.Data.SqlClient.EnableUserAgent";
private const string EnableMultiSubnetFailoverByDefaultString = @"Switch.Microsoft.Data.SqlClient.EnableMultiSubnetFailoverByDefault";

#if NET
private const string GlobalizationInvariantModeString = @"System.Globalization.Invariant";
Expand All @@ -52,6 +53,7 @@ private enum Tristate : byte
private static Tristate s_truncateScaledDecimal;
private static Tristate s_ignoreServerProvidedFailoverPartner;
private static Tristate s_enableUserAgent;
private static Tristate s_multiSubnetFailoverByDefault;

#if NET
private static Tristate s_globalizationInvariantMode;
Expand Down Expand Up @@ -511,6 +513,31 @@ public static bool DisableTnirByDefault
return s_disableTnirByDefault == Tristate.True;
}
}
#endif
#endif

/// <summary>
/// When set to true, the default value for MultiSubnetFailover connection string property
/// will be true instead of false. This enables parallel IP connection attempts for
/// improved connection times in multi-subnet environments.
/// This app context switch defaults to 'false'.
/// </summary>
public static bool EnableMultiSubnetFailoverByDefault
{
get
{
if (s_multiSubnetFailoverByDefault == Tristate.NotInitialized)
{
if (AppContext.TryGetSwitch(EnableMultiSubnetFailoverByDefaultString, out bool returnedValue) && returnedValue)
{
s_multiSubnetFailoverByDefault = Tristate.True;
}
else
{
s_multiSubnetFailoverByDefault = Tristate.False;
}
}
return s_multiSubnetFailoverByDefault == Tristate.True;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ public sealed class LocalAppContextSwitchesHelper : IDisposable
private readonly PropertyInfo _truncateScaledDecimalProperty;
private readonly PropertyInfo _ignoreServerProvidedFailoverPartner;
private readonly PropertyInfo _enableUserAgent;

#if NET
private readonly PropertyInfo _enableMultiSubnetFailoverByDefaultProperty;
#if NET
private readonly PropertyInfo _globalizationInvariantModeProperty;
#endif

Expand Down Expand Up @@ -69,8 +69,9 @@ public sealed class LocalAppContextSwitchesHelper : IDisposable
private readonly Tristate _ignoreServerProvidedFailoverPartnerOriginal;
private readonly FieldInfo _enableUserAgentField;
private readonly Tristate _enableUserAgentOriginal;

#if NET
private readonly FieldInfo _multiSubnetFailoverByDefaultField;
private readonly Tristate _multiSubnetFailoverByDefaultOriginal;
#if NET
private readonly FieldInfo _globalizationInvariantModeField;
private readonly Tristate _globalizationInvariantModeOriginal;
#endif
Expand Down Expand Up @@ -181,7 +182,11 @@ void InitProperty(string name, out PropertyInfo property)
"EnableUserAgent",
out _enableUserAgent);

#if NET
InitProperty(
"EnableMultiSubnetFailoverByDefault",
out _enableMultiSubnetFailoverByDefaultProperty);

#if NET
InitProperty(
"GlobalizationInvariantMode",
out _globalizationInvariantModeProperty);
Expand Down Expand Up @@ -269,7 +274,12 @@ void InitField(string name, out FieldInfo field, out Tristate value)
out _enableUserAgentField,
out _enableUserAgentOriginal);

#if NET
InitField(
"s_multiSubnetFailoverByDefault",
out _multiSubnetFailoverByDefaultField,
out _multiSubnetFailoverByDefaultOriginal);

#if NET
InitField(
"s_globalizationInvariantMode",
out _globalizationInvariantModeField,
Expand All @@ -281,8 +291,8 @@ void InitField(string name, out FieldInfo field, out Tristate value)
"s_useManagedNetworking",
out _useManagedNetworkingField,
out _useManagedNetworkingOriginal);
#endif
#endif

#if NETFRAMEWORK
InitField(
"s_disableTnirByDefault",
Expand Down Expand Up @@ -359,6 +369,10 @@ void RestoreField(FieldInfo field, Tristate value)
_enableUserAgentField,
_enableUserAgentOriginal);

RestoreField(
_multiSubnetFailoverByDefaultField,
_multiSubnetFailoverByDefaultOriginal);

#if NET
RestoreField(
_globalizationInvariantModeField,
Expand Down Expand Up @@ -474,6 +488,11 @@ public bool EnableUserAgent
get => (bool)_enableUserAgent.GetValue(null);
}

public bool EnableMultiSubnetFailoverByDefault
{
get => (bool)_enableMultiSubnetFailoverByDefaultProperty.GetValue(null);
}

#if NET
/// <summary>
/// Access the LocalAppContextSwitches.GlobalizationInvariantMode property.
Expand Down Expand Up @@ -608,7 +627,13 @@ public Tristate EnableUserAgentField
set => SetValue(_enableUserAgentField, value);
}

#if NET
public Tristate EnableMultiSubnetFailoverByDefaultField
{
get => GetValue(_multiSubnetFailoverByDefaultField);
set => SetValue(_multiSubnetFailoverByDefaultField, value);
}

#if NET
/// <summary>
/// Get or set the LocalAppContextSwitches.GlobalizationInvariantMode switch value.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public void TestDefaultAppContextSwitchValues()
Assert.True(LocalAppContextSwitches.UseCompatibilityAsyncBehaviour);
Assert.False(LocalAppContextSwitches.UseConnectionPoolV2);
Assert.False(LocalAppContextSwitches.TruncateScaledDecimal);
Assert.False(LocalAppContextSwitches.EnableMultiSubnetFailoverByDefault);
#if NETFRAMEWORK
Assert.False(LocalAppContextSwitches.DisableTnirByDefault);
Assert.False(LocalAppContextSwitches.UseManagedNetworking);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,48 @@ public void TestDefaultTnir(string dataSource, bool? tnirEnabledInConnString, Tr
Assert.Equal(expectedValue, connectionString.TransparentNetworkIPResolution);
}
#endif
/// <summary>
/// Test MSF values when set through connection string and through app context switch.
/// </summary>
[Theory]
[InlineData(true, Tristate.True, true)]
[InlineData(false, Tristate.True, false)]
[InlineData(null, Tristate.True, true)]
[InlineData(true, Tristate.False, true)]
[InlineData(false, Tristate.False, false)]
[InlineData(null, Tristate.False, false)]
[InlineData(null, Tristate.NotInitialized, false)]
public void TestDefaultMultiSubnetFailover(bool? msfInConnString, Tristate msfEnabledAppContext, bool expectedValue)
{
_appContextSwitchHelper.EnableMultiSubnetFailoverByDefaultField = msfEnabledAppContext;

SqlConnectionStringBuilder builder = new();
if (msfInConnString.HasValue)
{
builder.MultiSubnetFailover = msfInConnString.Value;
}
SqlConnectionString connectionString = new(builder.ConnectionString);

Assert.Equal(expectedValue, connectionString.MultiSubnetFailover);
}

/// <summary>
/// Tests that MultiSubnetFailover=true cannot be used with FailoverPartner.
/// </summary>
[Fact]
public void TestMultiSubnetFailoverWithFailoverPartnerThrows()
{
_appContextSwitchHelper.EnableMultiSubnetFailoverByDefaultField = Tristate.True;

SqlConnectionStringBuilder builder = new()
{
DataSource = "server",
FailoverPartner = "partner",
InitialCatalog = "database"
};

Assert.Throws<ArgumentException>(() => new SqlConnectionString(builder.ConnectionString));
}

public void Dispose()
{
Expand Down
Loading