Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Added PoolBlockingPeriod connection property #29697

Merged
merged 22 commits into from Jun 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6d9fe19
add Pool Blocking Period connection property
AfsanehR-zz May 14, 2018
b944ac6
update the assembly version
AfsanehR-zz May 14, 2018
d906f44
updated per review comments received and update assembly version
AfsanehR-zz May 14, 2018
9060418
Fixed an indentation
AfsanehR-zz May 14, 2018
a68899e
Fixed another indentation
AfsanehR-zz May 14, 2018
5777789
Fix for compilation issue
AfsanehR-zz May 14, 2018
47ac554
some review comments changes to make code cleaner
AfsanehR-zz May 15, 2018
c16c892
use other Assert methods in test and clear connection pool before eac…
AfsanehR-zz May 22, 2018
77fd936
Merge branch 'master' into PoolBlockingPeriod
AfsanehR-zz May 22, 2018
7e76fd8
Merge branch 'master' of https://github.com/dotnet/corefx into PoolBl…
AfsanehR-zz May 23, 2018
9590a9f
Merge branch 'master' of https://github.com/dotnet/corefx into PoolBl…
AfsanehR-zz May 23, 2018
83f124e
Merge branch 'master' of https://github.com/dotnet/corefx into PoolBl…
AfsanehR-zz May 23, 2018
563cb99
update version to 4.5.0.0
AfsanehR-zz May 23, 2018
3d592cd
Merge branch 'PoolBlockingPeriod' of https://github.com/v-afrafi/core…
AfsanehR-zz May 23, 2018
ec47490
make PoolBlockingPeriod to netcoreapp specific
AfsanehR-zz Jun 13, 2018
24bb30b
make PoolBlockingPeriod to netcoreapp specific
AfsanehR-zz Jun 13, 2018
edae126
Fixed System.Data.SqlClient.csproj file
AfsanehR-zz Jun 20, 2018
92c30d9
Fixed the double test file
AfsanehR-zz Jun 20, 2018
3551f7b
removed redundant test
AfsanehR-zz Jun 21, 2018
286eb8f
modified the test and addressed review comments
AfsanehR-zz Jun 26, 2018
365505a
updated test
AfsanehR-zz Jun 26, 2018
880e4f0
added a margin to test
AfsanehR-zz Jun 27, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/Microsoft.Private.PackageBaseline/packageIndex.json
Expand Up @@ -1239,7 +1239,7 @@
"monoandroid10": "Any",
"monotouch10": "Any",
"uap10.0.16299": "4.3.0.0",
"uap10.0.16300": "4.4.1.0",
"uap10.0.16300": "4.5.0.0",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joperezr are these changes in this commit sufficient for updating version?

"xamarinios10": "Any",
"xamarinmac20": "Any",
"xamarintvos10": "Any",
Expand All @@ -1251,7 +1251,7 @@
"4.1.1.0": "4.3.0",
"4.2.0.0": "4.4.0",
"4.4.0.0": "4.5.0",
"4.4.1.0": "4.6.0"
"4.5.0.0": "4.6.0"
}
},
"System.Data.SqlXml": {
Expand Down
2 changes: 1 addition & 1 deletion src/System.Data.SqlClient/dir.props
Expand Up @@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.4.1.0</AssemblyVersion>
<AssemblyVersion>4.5.0.0</AssemblyVersion>
<AssemblyKey>MSFT</AssemblyKey>
<IsUAP>true</IsUAP>
</PropertyGroup>
Expand Down
13 changes: 13 additions & 0 deletions src/System.Data.SqlClient/ref/System.Data.SqlClient.NetCoreApp.cs
Expand Up @@ -11,4 +11,17 @@ public partial class SqlDataReader : System.Data.Common.IDbColumnSchemaGenerator
{
public System.Collections.ObjectModel.ReadOnlyCollection<System.Data.Common.DbColumn> GetColumnSchema() { throw null; }
}

public enum PoolBlockingPeriod
{
Auto = 0,
AlwaysBlock = 1,
NeverBlock = 2,
}

public sealed partial class SqlConnectionStringBuilder : System.Data.Common.DbConnectionStringBuilder
{
public PoolBlockingPeriod PoolBlockingPeriod { get { throw null; } set { } }
}

}
Expand Up @@ -2,9 +2,13 @@
# netstandard dll has been shipped with IDbColumnSchemaGenerator inherited and SqlDataReader.GetColumnScheme() implemented in source, but not exposed in ref contract.
# Removing SqlDataReader.GetColumnScheme() from netstandard implementation potentially breaks existing customer source code
# that utilizes SqlDataReader.GetColumnScheme() indirectly by casting SqlDataReader to IDbColumnSchemaGenerator type.
# In order to prevent it, the API needs to be kept in public, and following 2 error message should be remaining in this baseline file.
# In order to prevent it, the API needs to be kept in public, and following 5 error message should be remaining in this baseline file.
#
# PoolBlockingPeriod was not added until .NET Framework 4.6.2, hence, the respective APIs are netcoreapp specific only.
Compat issues with assembly System.Data.SqlClient:
CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlClient.SqlDataReader' does not implement interface 'System.Data.Common.IDbColumnSchemaGenerator' in the reference but it does in the implementation.
MembersMustExist : Member 'System.Data.SqlClient.SqlDataReader.GetColumnSchema()' does not exist in the reference but it does exist in the implementation.
Total Issues: 2
TypesMustExist : Type 'System.Data.SqlClient.PoolBlockingPeriod' does not exist in the reference but it does exist in the implementation.
MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.PoolBlockingPeriod.get()' does not exist in the reference but it does exist in the implementation.
MembersMustExist : Member 'System.Data.SqlClient.SqlConnectionStringBuilder.PoolBlockingPeriod.set(System.Data.SqlClient.PoolBlockingPeriod)' does not exist in the reference but it does exist in the implementation.
Total Issues: 5
12 changes: 12 additions & 0 deletions src/System.Data.SqlClient/src/System.Data.SqlClient.csproj
Expand Up @@ -11,6 +11,9 @@
<AssemblyVersion Condition="'$(TargetGroup)' == 'netstandard1.2'">4.0.0.0</AssemblyVersion>
<AssemblyVersion Condition="'$(TargetGroup)' == 'netstandard1.3'">4.1.0.0</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetGroup)'=='netcoreapp'">
<DefineConstants>$(DefineConstants);netcoreapp</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
Expand All @@ -36,6 +39,9 @@
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard' OR '$(TargetGroup)' == 'netcoreapp' OR '$(IsUAPAssembly)' == 'true' ">
<Compile Include="System.Data.SqlClient.TypeForwards.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true' AND '$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netcoreapp'">
<Compile Include="System\Data\SqlClient\PoolBlockingPeriod.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true' AND '$(OSGroup)' != 'AnyOS'">
<Compile Include="Microsoft\SqlServer\Server\ITypedGetters.cs" />
<Compile Include="Microsoft\SqlServer\Server\ITypedGettersV3.cs" />
Expand Down Expand Up @@ -229,6 +235,12 @@
<Compile Include="Interop\SNINativeMethodWrapper.Common.cs" />
<Compile Include="System\Data\SqlClient\SqlCredential.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true' AND '$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netcoreapp'">
<Compile Include="System\Data\Common\DbConnectionStringCommon.NetCoreApp.cs"/>
<Compile Include="System\Data\ProviderBase\DbConnectionPool.NetCoreApp.cs" />
<Compile Include="System\Data\SqlClient\SqlConnectionString.NetCoreApp.cs" />
<Compile Include="System\Data\SqlClient\SqlConnectionStringBuilder.NetCoreApp.cs" />
</ItemGroup>
<!-- Manage the SNI toggle for Windows netstandard and UWP -->
<ItemGroup Condition="('$(TargetGroup)' == 'netstandard' OR '$(TargetGroup)' == 'netcoreapp') AND '$(TargetsWindows)' == 'true'">
<Compile Include="System\Data\SqlClient\TdsParserStateObjectFactory.Windows.cs" />
Expand Down
@@ -0,0 +1,146 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using System.Data.SqlClient;

namespace System.Data.Common
{
internal static partial class DbConnectionStringBuilderUtil
{
#region <<PoolBlockingPeriod Utility>>
internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result)
{
Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed");
Debug.Assert(null != value, "TryConvertToPoolBlockingPeriod(null,...)");

if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.Auto)))
{
result = PoolBlockingPeriod.Auto;
return true;
}
else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.AlwaysBlock)))
{
result = PoolBlockingPeriod.AlwaysBlock;
return true;
}
else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.NeverBlock)))
{
result = PoolBlockingPeriod.NeverBlock;
return true;
}
else
{
result = DbConnectionStringDefaults.PoolBlockingPeriod;
return false;
}
}

internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value)
{
Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed");
return (uint)value <= (uint)PoolBlockingPeriod.NeverBlock;
}

internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value)
{
Debug.Assert(IsValidPoolBlockingPeriodValue(value));

switch (value)
{
case PoolBlockingPeriod.AlwaysBlock:
return nameof(PoolBlockingPeriod.AlwaysBlock);
case PoolBlockingPeriod.NeverBlock:
return nameof(PoolBlockingPeriod.NeverBlock);
default:
return nameof(PoolBlockingPeriod.Auto);
}
}

/// <summary>
/// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is:
/// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer
/// * if the value is from type PoolBlockingPeriod, it will be used as is
/// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum
/// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException
///
/// in any case above, if the conerted value is out of valid range, the method raises ArgumentOutOfRangeException.
/// </summary>
/// <returns>PoolBlockingPeriod value in the valid range</returns>
internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value)
{
Debug.Assert(null != value, "ConvertToPoolBlockingPeriod(null)");
string sValue = (value as string);
PoolBlockingPeriod result;
if (null != sValue)
{
// We could use Enum.TryParse<PoolBlockingPeriod> here, but it accepts value combinations like
// "ReadOnly, ReadWrite" which are unwelcome here
// Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method.
if (TryConvertToPoolBlockingPeriod(sValue, out result))
{
return result;
}

// try again after remove leading & trailing whitespaces.
sValue = sValue.Trim();
if (TryConvertToPoolBlockingPeriod(sValue, out result))
{
return result;
}

// string values must be valid
throw ADP.InvalidConnectionOptionValue(keyword);
}
else
{
// the value is not string, try other options
PoolBlockingPeriod eValue;

if (value is PoolBlockingPeriod)
{
// quick path for the most common case
eValue = (PoolBlockingPeriod)value;
}
else if (value.GetType().IsEnum)
{
// explicitly block scenarios in which user tries to use wrong enum types, like:
// builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process;
// workaround: explicitly cast non-PoolBlockingPeriod enums to int
throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null);
}
else
{
try
{
// Enum.ToObject allows only integral and enum values (enums are blocked above), rasing ArgumentException for the rest
eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value);
}
catch (ArgumentException e)
{
// to be consistent with the messages we send in case of wrong type usage, replace
// the error with our exception, and keep the original one as inner one for troubleshooting
throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e);
}
}

// ensure value is in valid range
if (IsValidPoolBlockingPeriodValue(eValue))
{
return eValue;
}
else
{
throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue);
}
}
}
#endregion
}

internal static partial class DbConnectionStringDefaults
{
internal const PoolBlockingPeriod PoolBlockingPeriod = System.Data.SqlClient.PoolBlockingPeriod.Auto;
}
}
Expand Up @@ -13,7 +13,7 @@

namespace System.Data.Common
{
internal static class DbConnectionStringBuilderUtil
internal static partial class DbConnectionStringBuilderUtil
{
internal static bool ConvertToBoolean(object value)
{
Expand Down Expand Up @@ -306,6 +306,7 @@ internal static partial class DbConnectionStringKeywords
internal const string MaxPoolSize = "Max Pool Size";
internal const string Pooling = "Pooling";
internal const string MinPoolSize = "Min Pool Size";
internal const string PoolBlockingPeriod = "PoolBlockingPeriod";
}

internal static class DbConnectionStringSynonyms
Expand Down
@@ -0,0 +1,53 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using System.Data.Common;
using System.Data.SqlClient;

namespace System.Data.ProviderBase
{
sealed internal partial class DbConnectionPool
{
partial void CheckPoolBlockingPeriod(Exception e)
{
if (!IsBlockingPeriodEnabled())
{
throw e;
}
}

private bool IsBlockingPeriodEnabled()
{
var poolGroupConnectionOptions = _connectionPoolGroup.ConnectionOptions as SqlConnectionString;
if (poolGroupConnectionOptions == null)
{
return true;
}
var policy = poolGroupConnectionOptions.PoolBlockingPeriod;

switch (policy)
{
case System.Data.SqlClient.PoolBlockingPeriod.Auto:
{
return !ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource);
}
case System.Data.SqlClient.PoolBlockingPeriod.AlwaysBlock:
{
return true; //Enabled
}
case System.Data.SqlClient.PoolBlockingPeriod.NeverBlock:
{
return false; //Disabled
}
default:
{
//we should never get into this path.
Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement.");
return true;
}
}
}
}
}
Expand Up @@ -16,7 +16,7 @@

namespace System.Data.ProviderBase
{
sealed internal class DbConnectionPool
sealed internal partial class DbConnectionPool
{
private enum State
{
Expand Down Expand Up @@ -719,6 +719,9 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
{
throw;
}

CheckPoolBlockingPeriod(e);

newObj = null; // set to null, so we do not return bad new object
// Failed to create instance
_resError = e;
Expand Down Expand Up @@ -757,6 +760,9 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
return newObj;
}

//This method is implemented in DbConnectionPool.NetCoreApp
partial void CheckPoolBlockingPeriod(Exception e);

private void DeactivateObject(DbConnectionInternal obj)
{
obj.DeactivateConnection();
Expand Down
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


namespace System.Data.SqlClient
{
public enum PoolBlockingPeriod
{
Auto = 0, // Blocking period OFF for Azure SQL servers, but ON for all other SQL servers.
AlwaysBlock = 1, // Blocking period ON for all SQL servers including Azure SQL servers.
NeverBlock = 2, // Blocking period OFF for all SQL servers including Azure SQL servers.
}
}
@@ -0,0 +1,38 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Data.Common;

namespace System.Data.SqlClient
{
internal sealed partial class SqlConnectionString : DbConnectionOptions
{
internal static partial class DEFAULT
{
internal const PoolBlockingPeriod PoolBlockingPeriod = DbConnectionStringDefaults.PoolBlockingPeriod;
}

private readonly PoolBlockingPeriod _poolBlockingPeriod;

internal PoolBlockingPeriod PoolBlockingPeriod { get { return _poolBlockingPeriod; } }

internal System.Data.SqlClient.PoolBlockingPeriod ConvertValueToPoolBlockingPeriod()
{
string value;
if (!TryGetParsetableValue(KEY.PoolBlockingPeriod, out value))
{
return DEFAULT.PoolBlockingPeriod;
}

try
{
return DbConnectionStringBuilderUtil.ConvertToPoolBlockingPeriod(KEY.PoolBlockingPeriod, value);
}
catch (Exception e) when (e is FormatException || e is OverflowException)
{
throw ADP.InvalidConnectionOptionValue(KEY.PoolBlockingPeriod, e);
}
}
}
}