diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index 001a94e540..9f4da39069 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -160,6 +160,7 @@ Tests can be built and run with custom Target Frameworks. See the below examples # Build the tests for custom TargetFramework (.NET Core) # Applicable values: netcoreapp2.1 | netcoreapp2.2 | netcoreapp3.0 ``` + ### Running Tests: ```bash @@ -171,3 +172,9 @@ Tests can be built and run with custom Target Frameworks. See the below examples # Use above property to run Functional Tests with custom TargetFramework (.NET Core) # Applicable values: netcoreapp2.1 | netcoreapp2.2 | netcoreapp3.0 ``` + +## Using Managed SNI on Windows + +Managed SNI can be enabled on Windows by enabling the below AppContext switch: + +**"Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows"** diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectFactory.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectFactory.Windows.cs index 2e145c4bd8..2f609b5d91 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectFactory.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectFactory.Windows.cs @@ -9,25 +9,15 @@ namespace Microsoft.Data.SqlClient { internal sealed class TdsParserStateObjectFactory { - - private const string UseLegacyNetworkingOnWindows = "Microsoft.Data.SqlClient.UseLegacyNetworkingOnWindows"; - public static readonly TdsParserStateObjectFactory Singleton = new TdsParserStateObjectFactory(); + private const string UseManagedNetworkingOnWindows = "Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows"; - // Temporary disabling App Context switching for managed SNI. - // If the appcontext switch is set then Use Managed SNI based on the value. Otherwise Managed SNI should always be used. - //private static bool shouldUseLegacyNetorking; - //public static bool UseManagedSNI { get; } = AppContext.TryGetSwitch(UseLegacyNetworkingOnWindows, out shouldUseLegacyNetorking) ? !shouldUseLegacyNetorking : true; + private static bool shouldUseManagedSNI; -#if DEBUG - private static Lazy useManagedSNIOnWindows = new Lazy( - () => bool.TrueString.Equals(Environment.GetEnvironmentVariable("Microsoft.Data.SqlClient.UseManagedSNIOnWindows"), StringComparison.InvariantCultureIgnoreCase) - ); - public static bool UseManagedSNI => useManagedSNIOnWindows.Value; -#else - public static bool UseManagedSNI { get; } = false; -#endif + // If the appcontext switch is set then Use Managed SNI based on the value. Otherwise Native SNI.dll will be used by default. + public static bool UseManagedSNI { get; } = + AppContext.TryGetSwitch(UseManagedNetworkingOnWindows, out shouldUseManagedSNI) ? shouldUseManagedSNI : false; public EncryptionOptions EncryptionOptions { @@ -49,10 +39,14 @@ public TdsParserStateObject CreateTdsParserStateObject(TdsParser parser) { if (UseManagedSNI) { + SqlClientEventSource.Log.TraceEvent(" Found AppContext switch '{0}#' enabled, managed networking implementation will be used." + , UseManagedNetworkingOnWindows); return new TdsParserStateObjectManaged(parser); } else { + SqlClientEventSource.Log.TraceEvent(" AppContext switch '{0}#' not enabled, native networking implementation will be used." + , UseManagedNetworkingOnWindows); return new TdsParserStateObjectNative(parser); } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs index ea3def41a0..2a73c38487 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs @@ -45,9 +45,10 @@ public static class DataTestUtility public const string UdtTestDbName = "UdtTestDb"; public const string AKVKeyName = "TestSqlClientAzureKeyVaultProvider"; - private static readonly Assembly MdsAssembly = typeof(Microsoft.Data.SqlClient.SqlConnection).GetTypeInfo().Assembly; - private static readonly Type TdsParserStateObjectFactoryInstance = MdsAssembly?.GetType("Microsoft.Data.SqlClient.TdsParserStateObjectFactory"); - private static readonly PropertyInfo UseManagedSni = TdsParserStateObjectFactoryInstance?.GetProperty("UseManagedSNI", BindingFlags.Static | BindingFlags.Public); + private const string ManagedNetworkingAppContextSwitch = "Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows"; + + private static bool UseManagedSNI = + bool.TryParse(Environment.GetEnvironmentVariable("Microsoft_Data_SqlClient_UseManagedSniOnWindows"), out UseManagedSNI) ? UseManagedSNI : false; private static readonly string[] AzureSqlServerEndpoints = {".database.windows.net", ".database.cloudapi.de", @@ -76,6 +77,12 @@ private class Config static DataTestUtility() { + if (UseManagedSNI) + { + AppContext.SetSwitch(ManagedNetworkingAppContextSwitch, true); + Console.WriteLine($"App Context switch {ManagedNetworkingAppContextSwitch} enabled on {Environment.OSVersion}"); + } + using (StreamReader r = new StreamReader("config.json")) { string json = r.ReadToEnd(); @@ -231,7 +238,7 @@ public static bool IsAKVSetupAvailable() return !string.IsNullOrEmpty(AKVUrl) && !string.IsNullOrEmpty(AKVClientId) && !string.IsNullOrEmpty(AKVClientSecret); } - public static bool IsUsingManagedSNI() => (bool)(UseManagedSni?.GetValue(null) ?? false); + public static bool IsUsingManagedSNI() => UseManagedSNI; public static bool IsUsingNativeSNI() => !IsUsingManagedSNI(); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/IntegratedAuthenticationTest/IntegratedAuthenticationTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/IntegratedAuthenticationTest/IntegratedAuthenticationTest.cs index 05fe3ab782..b766502833 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/IntegratedAuthenticationTest/IntegratedAuthenticationTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/IntegratedAuthenticationTest/IntegratedAuthenticationTest.cs @@ -9,8 +9,8 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests public static class IntegratedAuthenticationTest { private static bool IsIntegratedSecurityEnvironmentSet() => DataTestUtility.IsIntegratedSecuritySetup(); - private static bool AreConnectionStringsSetup() => DataTestUtility.AreConnStringsSetup(); + private static bool AreConnectionStringsSetup() => DataTestUtility.AreConnStringsSetup(); [ConditionalFact(nameof(IsIntegratedSecurityEnvironmentSet), nameof(AreConnectionStringsSetup))] public static void IntegratedAuthenticationTestWithConnectionPooling()