Imported Upstream version 5.16.0.100

Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-08-07 15:19:03 +00:00
parent 0a9828183b
commit 7d7f676260
4419 changed files with 170950 additions and 90273 deletions

View File

@@ -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.3.1.0</AssemblyVersion>
<AssemblyVersion>4.4.0.0</AssemblyVersion>
<AssemblyKey>MSFT</AssemblyKey>
<IsUAP>true</IsUAP>
</PropertyGroup>

View File

@@ -3,13 +3,9 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Data.SqlClient.csproj">
<SupportedFramework>net461;netcoreapp2.0;$(UAPvNextTFM);$(AllXamarinFrameworks)</SupportedFramework>
<SupportedFramework>net461;netcoreapp2.0;uap10.0.16299;$(UAPvNextTFM);$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Data.SqlClient.csproj" />
<InboxOnTargetFramework Include="$(UAPvNextTFM)" />
<File Include="$(PlaceHolderFile)">
<TargetPath>runtimes/win/lib/$(UAPvNextTFM)</TargetPath>
</File>
<HarvestIncludePaths Include="ref/net451;lib/net451;runtimes/win/lib/net451" />
<HarvestIncludePaths Include="ref/net46;lib/net46;runtimes/win/lib/net46" />
<HarvestIncludePaths Include="ref/netstandard1.2">
@@ -19,6 +15,15 @@
<SupportedFramework>net46;netcoreapp1.0</SupportedFramework>
</HarvestIncludePaths>
<HarvestIncludePaths Include="runtimes/unix/lib/netstandard1.3;runtimes/win/lib/netstandard1.3" />
<!-- Since UAP and .NETCoreApp are package based we still want to enable
OOBing libraries that happen to overlap with their framework package.
This avoids us having to lock the API in our NuGet packages just
to match what shipped inbox: since we can provide a new library
we can update it to add API without raising the netstandard version. -->
<ValidatePackageSuppression Include="TreatAsOutOfBox">
<Value>.NETCoreApp;UAP</Value>
</ValidatePackageSuppression>
</ItemGroup>
<ItemGroup>
<InboxOnTargetFramework Include="$(AllXamarinFrameworks)" />

View File

@@ -4,6 +4,7 @@
<BuildConfigurations>
netstandard;
netfx;
netcoreapp;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -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.
// ------------------------------------------------------------------------------
// Changes to this file must follow the http://aka.ms/api-review process.
// ------------------------------------------------------------------------------
namespace System.Data.SqlClient
{
public partial class SqlDataReader : System.Data.Common.IDbColumnSchemaGenerator
{
public System.Collections.ObjectModel.ReadOnlyCollection<System.Data.Common.DbColumn> GetColumnSchema() { throw null; }
}
}

View File

@@ -158,7 +158,12 @@ namespace Microsoft.SqlServer.Server
public SqlMetaData(string name, System.Data.SqlDbType dbType, long maxLength, long locale, System.Data.SqlTypes.SqlCompareOptions compareOptions, bool useServerDefault, bool isUniqueKey, System.Data.SqlClient.SortOrder columnSortOrder, int sortOrdinal) { }
public SqlMetaData(string name, System.Data.SqlDbType dbType, string database, string owningSchema, string objectName) { }
public SqlMetaData(string name, System.Data.SqlDbType dbType, string database, string owningSchema, string objectName, bool useServerDefault, bool isUniqueKey, System.Data.SqlClient.SortOrder columnSortOrder, int sortOrdinal) { }
public SqlMetaData(string name, System.Data.SqlDbType dbType, System.Type userDefinedType) { }
public SqlMetaData(string name, System.Data.SqlDbType dbType, System.Type userDefinedType, string serverTypeName) { }
public SqlMetaData(string name, System.Data.SqlDbType dbType, System.Type userDefinedType, string serverTypeName, bool useServerDefault, bool isUniqueKey, System.Data.SqlClient.SortOrder columnSortOrder, int sortOrdinal) { }
public System.Data.SqlTypes.SqlCompareOptions CompareOptions { get { throw null; } }
public System.Data.DbType DbType { get { throw null; } }
public bool IsUniqueKey { get { throw null; } }
public long LocaleId { get { throw null; } }
public static long Max { get { throw null; } }
@@ -169,6 +174,7 @@ namespace Microsoft.SqlServer.Server
public System.Data.SqlClient.SortOrder SortOrder { get { throw null; } }
public int SortOrdinal { get { throw null; } }
public System.Data.SqlDbType SqlDbType { get { throw null; } }
public System.Type Type{ get { throw null; } }
public string TypeName { get { throw null; } }
public bool UseServerDefault { get { throw null; } }
public string XmlSchemaCollectionDatabase { get { throw null; } }
@@ -416,6 +422,9 @@ namespace System.Data.SqlClient
public System.Xml.XmlReader ExecuteXmlReader() { throw null; }
public System.Threading.Tasks.Task<System.Xml.XmlReader> ExecuteXmlReaderAsync() { throw null; }
public System.Threading.Tasks.Task<System.Xml.XmlReader> ExecuteXmlReaderAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
public System.IAsyncResult BeginExecuteXmlReader() { throw null; }
public System.IAsyncResult BeginExecuteXmlReader(System.AsyncCallback callback, object stateObject) { throw null; }
public System.Xml.XmlReader EndExecuteXmlReader(System.IAsyncResult asyncResult) { throw null; }
public override void Prepare() { }
public System.Data.Sql.SqlNotificationRequest Notification { get { throw null; } set { } }
public void ResetCommandTimeout() { }
@@ -451,6 +460,7 @@ namespace System.Data.SqlClient
{
public SqlConnection() { }
public SqlConnection(string connectionString) { }
public SqlConnection(string connectionString, System.Data.SqlClient.SqlCredential credential) { }
public System.Guid ClientConnectionId { get { throw null; } }
object ICloneable.Clone() { throw null; }
public override string ConnectionString { get { throw null; } set { } }
@@ -463,6 +473,7 @@ namespace System.Data.SqlClient
public override System.Data.ConnectionState State { get { throw null; } }
public bool StatisticsEnabled { get { throw null; } set { } }
public string WorkstationId { get { throw null; } }
public System.Data.SqlClient.SqlCredential Credential { get { throw null; } set { } }
public event System.Data.SqlClient.SqlInfoMessageEventHandler InfoMessage { add { } remove { } }
protected override System.Data.Common.DbTransaction BeginDbTransaction(System.Data.IsolationLevel isolationLevel) { throw null; }
public new System.Data.SqlClient.SqlTransaction BeginTransaction() { throw null; }
@@ -475,10 +486,16 @@ namespace System.Data.SqlClient
public override void Close() { }
public new System.Data.SqlClient.SqlCommand CreateCommand() { throw null; }
protected override System.Data.Common.DbCommand CreateDbCommand() { throw null; }
public override System.Data.DataTable GetSchema() { throw null; }
public override System.Data.DataTable GetSchema(string collectionName) { throw null; }
public override System.Data.DataTable GetSchema(string collectionName, string[] restrictionValues) { throw null; }
public override void Open() { }
public override System.Threading.Tasks.Task OpenAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
public void ResetStatistics() { }
public System.Collections.IDictionary RetrieveStatistics() { throw null; }
public static void ChangePassword(string connectionString, string newPassword) { throw null; }
public static void ChangePassword(string connectionString, System.Data.SqlClient.SqlCredential credential, System.Security.SecureString newPassword) { throw null; }
}
public sealed partial class SqlConnectionStringBuilder : System.Data.Common.DbConnectionStringBuilder
{
@@ -678,6 +695,7 @@ namespace System.Data.SqlClient
public virtual object GetSqlValue(int i) { throw null; }
public virtual int GetSqlValues(object[] values) { throw null; }
public virtual System.Data.SqlTypes.SqlXml GetSqlXml(int i) { throw null; }
public override System.Data.DataTable GetSchemaTable() { throw null; }
public override System.IO.Stream GetStream(int i) { throw null; }
public override string GetString(int i) { throw null; }
public override System.IO.TextReader GetTextReader(int i) { throw null; }
@@ -686,6 +704,7 @@ namespace System.Data.SqlClient
public override int GetValues(object[] values) { throw null; }
public virtual System.Xml.XmlReader GetXmlReader(int i) { throw null; }
public override bool IsDBNull(int i) { throw null; }
protected internal bool IsCommandBehavior(System.Data.CommandBehavior condition) { throw null; }
public override System.Threading.Tasks.Task<bool> IsDBNullAsync(int i, System.Threading.CancellationToken cancellationToken) { throw null; }
public override bool NextResult() { throw null; }
public override System.Threading.Tasks.Task<bool> NextResultAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
@@ -779,6 +798,8 @@ namespace System.Data.SqlClient
{
internal SqlParameterCollection() { }
public override int Count { get { throw null; } }
public override bool IsFixedSize { get { throw null; } }
public override bool IsReadOnly { get { throw null; } }
public new System.Data.SqlClient.SqlParameter this[int index] { get { throw null; } set { } }
public new System.Data.SqlClient.SqlParameter this[string parameterName] { get { throw null; } set { } }
public override object SyncRoot { get { throw null; } }
@@ -830,6 +851,13 @@ namespace System.Data.SqlClient
public void Rollback(string transactionName) { }
public void Save(string savePointName) { }
}
public sealed class SqlCredential
{
public SqlCredential(string userId, System.Security.SecureString password) { }
public string UserId { get { throw null; } }
public System.Security.SecureString Password { get { throw null; } }
}
}
namespace System.Data
{

View File

@@ -4,24 +4,35 @@
<PropertyGroup>
<ProjectGuid>{D58E8D2B-3331-4660-8DFB-512D66F8EC63}</ProjectGuid>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
<!-- Must match version supported by frameworks which support 4.3.* inbox.
Can be removed when API is added and this assembly is versioned to 4.4.* -->
<AssemblyVersion Condition="'$(TargetsNetFx)' != 'true'">4.3.1.0</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
<ItemGroup>
<SuppressPackageTargetFrameworkCompatibility Include="$(UAPvNextTFM)" />
<SuppressPackageTargetFrameworkCompatibility Include="$(UAPvNextTFM);uap10.0.16299" />
<Compile Include="System.Data.SqlClient.cs" />
<Compile Include="System.Data.SqlClient.Manual.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
<Compile Include="System.Data.SqlClient.NetCoreApp.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.Runtime.Extensions\ref\System.Runtime.Extensions.csproj" />
<ProjectReference Include="..\..\System.Data.Common\ref\System.Data.Common.csproj" />
<ProjectReference Include="..\..\System.Collections.NonGeneric\ref\System.Collections.NonGeneric.csproj" />
<ProjectReference Include="..\..\System.ComponentModel.Primitives\ref\System.ComponentModel.Primitives.csproj" />
<ProjectReference Include="..\..\System.Xml.ReaderWriter\ref\System.Xml.ReaderWriter.csproj" />
<ProjectReference Include="..\..\System.Runtime.InteropServices\ref\System.Runtime.InteropServices.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -8,10 +8,14 @@
netstandard1.3;
netstandard;
netfx-Windows_NT;
netcoreapp;
netcoreapp-Unix;
netcoreapp-Windows_NT;
uap10.0.16299-Windows_NT;
uap-Windows_NT;
</PackageConfigurations>
<BuildConfigurations>
$(PackageConfigurations)
uap-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,10 @@
#
# 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.
#
Compat issues with assembly System.Data.SqlClient:
CannotRemoveBaseTypeOrInterface : Type 'System.Data.SqlClient.SqlDataReader' does not implement interface 'System.Data.Common.IDbColumnSchemaGenerator' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Data.SqlClient.SqlDataReader.GetColumnSchema()' does not exist in the implementation but it does exist in the contract.
Total Issues: 2

View File

@@ -729,7 +729,7 @@ namespace Microsoft.SqlServer.Server
}
}
IDataReader System.Data.IDataRecord.GetData (int ordinal)
IDataReader System.Data.IDataRecord.GetData(int ordinal)
{
throw ADP.NotSupported();
}

View File

@@ -0,0 +1,44 @@
<!-- Not a bug. sni.dll is a native component that ships as part of the package. -->
kernel32.dll!LoadLibraryExW
sni.dll!GetSniMaxComposedSpnLength
sni.dll!SNIAddProviderWrapper
sni.dll!SNICheckConnectionWrapper
sni.dll!SNICloseWrapper
sni.dll!SNIGetInfoWrapper
sni.dll!SNIGetLastError
sni.dll!SNIInitialize
sni.dll!SNIOpenSyncExWrapper
sni.dll!SNIOpenWrapper
sni.dll!SNIPacketAllocateWrapper
sni.dll!SNIPacketGetDataWrapper
sni.dll!SNIPacketRelease
sni.dll!SNIPacketResetWrapper
sni.dll!SNIPacketSetData
sni.dll!SNIQueryInfo
sni.dll!SNIReadAsyncWrapper
sni.dll!SNIReadSyncOverAsync
sni.dll!SNIRemoveProviderWrapper
sni.dll!SNISecGenClientContextWrapper
sni.dll!SNISecInitPackage
sni.dll!SNISetInfoWrapper
sni.dll!SNITerminate
sni.dll!SNIWaitForSSLHandshakeToCompleteWrapper
sni.dll!SNIWriteAsyncWrapper
sni.dll!SNIWriteSyncOverAsync
sni.dll!UnmanagedIsTokenRestricted
sspicli.dll!AcceptSecurityContext
sspicli.dll!AcquireCredentialsHandleW
sspicli.dll!ApplyControlToken
sspicli.dll!CompleteAuthToken
sspicli.dll!DecryptMessage
sspicli.dll!DeleteSecurityContext
sspicli.dll!EncryptMessage
sspicli.dll!EnumerateSecurityPackagesW
sspicli.dll!FreeContextBuffer
sspicli.dll!FreeCredentialsHandle
sspicli.dll!InitializeSecurityContextW
sspicli.dll!QueryContextAttributesW
sspicli.dll!QuerySecurityContextToken
sspicli.dll!SetContextAttributesW
sspicli.dll!SspiEncodeStringsAsAuthIdentity
sspicli.dll!SspiFreeAuthIdentity

View File

@@ -1,5 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
@@ -431,7 +490,7 @@
<value>Failed to generate SSPI context.</value>
</data>
<data name="SQL_KerberosTicketMissingError" xml:space="preserve">
<value>Cannot access Kerberos ticket. Ensure Kerberos has been initialized with 'kinit'.</value>
<value>Cannot authenticate using Kerberos. Ensure Kerberos has been initialized on the client with 'kinit' and a Service Principal Name has been registered for the SQL Server to allow Kerberos authentication.</value>
</data>
<data name="SQL_SqlServerBrowserNotAccessible" xml:space="preserve">
<value>Cannot connect to SQL Server Browser. Ensure SQL Server Browser has been started.</value>
@@ -1091,7 +1150,7 @@
<value>TCP Provider</value>
</data>
<data name="SNI_PN8" xml:space="preserve">
<value></value>
<value />
</data>
<data name="SNI_PN9" xml:space="preserve">
<value>SQL Network Interfaces</value>
@@ -1165,32 +1224,32 @@
<data name="SqlProvider_InvalidDataColumnMaxLength" xml:space="preserve">
<value>The size of column '{0}' is not supported. The size is {1}.</value>
</data>
<data name="MDF_InvalidXmlInvalidValue" xml:space="preserve">
<data name="MDF_InvalidXmlInvalidValue" xml:space="preserve">
<value>The metadata XML is invalid. The {1} column of the {0} collection must contain a non-empty string.</value>
</data>
<data name="MDF_CollectionNameISNotUnique" xml:space="preserve">
<data name="MDF_CollectionNameISNotUnique" xml:space="preserve">
<value>There are multiple collections named '{0}'.</value>
</data>
<data name="MDF_InvalidXmlMissingColumn" xml:space="preserve">
<data name="MDF_InvalidXmlMissingColumn" xml:space="preserve">
<value>The metadata XML is invalid. The {0} collection must contain a {1} column and it must be a string column.</value>
</data>
<data name="MDF_InvalidXml" xml:space="preserve">
<data name="MDF_InvalidXml" xml:space="preserve">
<value>The metadata XML is invalid.</value>
</data>
<data name="MDF_NoColumns" xml:space="preserve">
<data name="MDF_NoColumns" xml:space="preserve">
<value>The schema table contains no columns.</value>
</data>
<data name="MDF_QueryFailed" xml:space="preserve">
<data name="MDF_QueryFailed" xml:space="preserve">
<value>Unable to build the '{0}' collection because execution of the SQL query failed. See the inner exception for details.</value>
</data>
<data name="MDF_TooManyRestrictions" xml:space="preserve">
<data name="MDF_TooManyRestrictions" xml:space="preserve">
<value>More restrictions were provided than the requested schema ('{0}') supports.</value>
</data>
<data name="MDF_DataTableDoesNotExist" xml:space="preserve">
<data name="MDF_DataTableDoesNotExist" xml:space="preserve">
<value>The collection '{0}' is missing from the metadata XML.</value>
</data>
<data name="MDF_UndefinedCollection" xml:space="preserve">
<value>The requested collection ({0}) is not defined.</value>
<data name="MDF_UndefinedCollection" xml:space="preserve">
<value>The requested collection ({0}) is not defined.</value>
</data>
<data name="MDF_UnsupportedVersion" xml:space="preserve">
<value> requested collection ({0}) is not supported by this version of the provider.</value>
@@ -1213,4 +1272,28 @@
<data name="MDF_UnableToBuildCollection" xml:space="preserve">
<value>Unable to build schema collection '{0}';</value>
</data>
<data name="ADP_InvalidArgumentLength" xml:space="preserve">
<value>The length of argument '{0}' exceeds its limit of '{1}'.</value>
</data>
<data name="ADP_MustBeReadOnly" xml:space="preserve">
<value>{0} must be marked as read only.</value>
</data>
<data name="ADP_InvalidMixedUsageOfSecureAndClearCredential" xml:space="preserve">
<value>Cannot use Credential with UserID, UID, Password, or PWD connection string keywords.</value>
</data>
<data name="ADP_InvalidMixedUsageOfSecureCredentialAndIntegratedSecurity" xml:space="preserve">
<value>Cannot use Credential with Integrated Security connection string keyword.</value>
</data>
<data name="SQL_ChangePasswordArgumentMissing" xml:space="preserve">
<value>The '{0}' argument must not be null or empty.</value>
</data>
<data name="SQL_ChangePasswordConflictsWithSSPI" xml:space="preserve">
<value>ChangePassword can only be used with SQL authentication, not with integrated security.</value>
</data>
<data name="SQL_ChangePasswordRequiresYukon" xml:space="preserve">
<value>ChangePassword requires SQL Server 9.0 or later.</value>
</data>
<data name="SQL_ChangePasswordUseOfUnallowedKey" xml:space="preserve">
<value>The keyword '{0}' must not be specified in the connectionString argument to ChangePassword.</value>
</data>
</root>

View File

@@ -6,6 +6,7 @@
<AssemblyName>System.Data.SqlClient</AssemblyName>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
<IsUAPAssembly Condition="'$(TargetGroup)' == 'uap' OR '$(TargetGroup)' == 'uap10.0.16299'">true</IsUAPAssembly>
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(OSGroup)' == 'AnyOS'">SR.PlatformNotSupported_DataSqlClient</GeneratePlatformNotSupportedAssemblyMessage>
<AssemblyVersion Condition="'$(TargetGroup)' == 'netstandard1.2'">4.0.0.0</AssemblyVersion>
<AssemblyVersion Condition="'$(TargetGroup)' == 'netstandard1.3'">4.1.0.0</AssemblyVersion>
@@ -14,6 +15,8 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap10.0.16299-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap10.0.16299-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Unix-Debug|AnyCPU'" />
@@ -24,7 +27,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.2-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.3-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.3-Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard' OR '$(TargetGroup)' == 'uap' ">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<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'">
@@ -55,6 +64,9 @@
<Compile Include="$(CommonPath)\System\Data\Common\AdapterUtil.cs">
<Link>System\Data\Common\AdapterUtil.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Data\Common\AdapterUtil.Drivers.cs">
<Link>System\Data\Common\AdapterUtil.Drivers.cs</Link>
</Compile>
<Compile Include="System\Data\Common\AdapterUtil.SqlClient.cs" />
<Compile Include="System\Data\Common\SR.cs" />
<Compile Include="System\Data\Common\DbConnectionOptions.cs" />
@@ -77,18 +89,35 @@
<Compile Include="$(CommonPath)\System\Data\Common\NameValuePair.cs">
<Link>System\Data\Common\NameValuePair.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Data\ProviderBase\DbConnectionInternal.cs">
<Link>Common\System\Data\ProviderBase\DbConnectionInternal.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Data\ProviderBase\DbConnectionFactory.cs">
<Link>Common\System\Data\ProviderBase\DbConnectionFactory.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Data\ProviderBase\DbConnectionPoolGroup.cs">
<Link>Common\System\Data\ProviderBase\DbConnectionPoolGroup.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Data\ProviderBase\TimeoutTimer.cs">
<Link>Common\System\Data\ProviderBase\TimeoutTimer.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Data\ProviderBase\DbReferenceCollection.cs">
<Link>Common\System\Data\ProviderBase\DbReferenceCollection.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Data\ProviderBase\DbMetaDataFactory.cs">
<Link>Common\System\Data\ProviderBase\DbMetaDataFactory.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Data\ProviderBase\DbConnectionClosed.cs">
<Link>Common\System\Data\ProviderBase\DbConnectionClosed.cs</Link>
</Compile>
<Compile Include="System\Data\ProviderBase\DbConnectionClosed.cs" />
<Compile Include="System\Data\ProviderBase\DbConnectionFactory.cs" />
<Compile Include="System\Data\ProviderBase\DbConnectionInternal.cs" />
<Compile Include="System\Data\ProviderBase\DbConnectionPool.cs" />
<Compile Include="System\Data\ProviderBase\DbConnectionPoolGroup.cs" />
<Compile Include="System\Data\ProviderBase\DbConnectionPoolGroupProviderInfo.cs" />
<Compile Include="System\Data\ProviderBase\DbConnectionPoolIdentity.cs" />
<Compile Include="System\Data\ProviderBase\DbConnectionPoolOptions.cs" />
<Compile Include="System\Data\ProviderBase\DbConnectionPoolProviderInfo.cs" />
<Compile Include="System\Data\ProviderBase\DbMetaDataFactory.cs" />
<Compile Include="System\Data\ProviderBase\DbReferenceCollection.cs" />
<Compile Include="System\Data\ProviderBase\TimeoutTimer.cs" />
<Compile Include="System\Data\Sql\IBinarySerialize.cs" />
<Compile Include="System\Data\Sql\InvalidUdtException.cs" />
<Compile Include="System\Data\Sql\SqlFunctionAttribute.cs" />
@@ -198,12 +227,13 @@
<Compile Include="System\Data\SqlClient\SNI\SSRP.cs" />
<Compile Include="System\Data\SqlClient\TdsParserStateObjectManaged.cs" />
<Compile Include="Interop\SNINativeMethodWrapper.Common.cs" />
<Compile Include="System\Data\SqlClient\SqlCredential.cs" />
</ItemGroup>
<!-- Manage the SNI toggle for Windows netstandard and UWP -->
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard' AND '$(TargetsWindows)' == 'true'">
<ItemGroup Condition="('$(TargetGroup)' == 'netstandard' OR '$(TargetGroup)' == 'netcoreapp') AND '$(TargetsWindows)' == 'true'">
<Compile Include="System\Data\SqlClient\TdsParserStateObjectFactory.Windows.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'uap'">
<ItemGroup Condition="'$(IsUAPAssembly)' == 'true'">
<Compile Include="System\Data\SqlClient\TdsParserStateObjectFactory.Managed.cs" />
<Compile Include="System\Data\SqlClient\LocalDBAPI.uap.cs" />
<Compile Include="System\Data\SqlClient\SNI\LocalDB.uap.cs" />
@@ -211,7 +241,7 @@
<Compile Include="System\Data\SqlClient\TdsParser.Unix.cs" />
</ItemGroup>
<!-- Assets needed on Windows but should be avoided on UAP to avoid sni.dll -->
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' And '$(IsPartialFacadeAssembly)' != 'true' and '$(TargetGroup)' != 'uap' ">
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' And '$(IsPartialFacadeAssembly)' != 'true' and '$(IsUAPAssembly)' != 'true'">
<Compile Include="System\Data\SqlClient\TdsParserStateObjectNative.cs" />
<Compile Include="Interop\SNINativeMethodWrapper.Windows.cs" />
<Compile Include="System\Data\SqlClient\TdsParserSafeHandles.cs" />
@@ -286,9 +316,6 @@
<Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecurityPackageInfo.cs">
<Link>Common\Interop\Windows\sspicli\SecurityPackageInfo.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Net\IntPtrHelper.cs">
<Link>Common\System\Net\IntPtrHelper.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\sspicli\SSPIAuthType.cs">
<Link>Common\Interop\Windows\sspicli\SSPIAuthType.cs</Link>
</Compile>
@@ -406,7 +433,7 @@
<Compile Include="System\Data\SqlClient\LocalDBAPI.Unix.cs" />
<Compile Include="System\Data\SqlClient\SNI\LocalDB.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)' == 'true' And '$(IsPartialFacadeAssembly)' != 'true' and '$(TargetGroup)' != 'uap'">
<ItemGroup Condition="'$(TargetsWindows)' == 'true' And '$(IsPartialFacadeAssembly)' != 'true' and '$(IsUAPAssembly)' != 'true'">
<Reference Include="Microsoft.Win32.Registry" />
</ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
@@ -420,6 +447,7 @@
</ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true' AND '$(OSGroup)' != 'AnyOS'">
<Reference Include="Microsoft.Win32.Primitives" />
<Reference Include="System.Buffers" />
<Reference Include="System.Collections" />
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.ComponentModel" />
@@ -450,7 +478,7 @@
<Reference Include="System.Net.NameResolution" />
<Reference Include="System.Diagnostics.Tracing" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'uap'">
<ItemGroup Condition="('$(OSGroup)' != 'AnyOS' AND '$(IsUAPAssembly)' == 'true') OR '$(TargetGroup)' == 'netcoreapp'">
<Reference Include="System.Transactions.Local" />
<Reference Include="System.Collections.NonGeneric" />
</ItemGroup>
@@ -463,6 +491,13 @@
<LogicalName>System.Data.SqlClient.SqlMetaData.xml</LogicalName>
</EmbeddedResource>
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
<Reference Include="System.Runtime.Extensions" />
<Reference Include="System.Data.Common" />
<Reference Include="System.ComponentModel.Primitives" />
<Reference Include="System.Xml.ReaderWriter" />
<Reference Include="System.Runtime.InteropServices" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
<Import Project=".\GenerateThisAssemblyCs.targets" Condition="'$(IsPartialFacadeAssembly)' != 'true'" />
</Project>
</Project>

View File

@@ -880,5 +880,35 @@ namespace System.Data.Common
TraceExceptionAsReturnValue(e);
return e;
}
internal static ArgumentException InvalidArgumentLength(string argumentName, int limit)
{
return Argument(SR.GetString(SR.ADP_InvalidArgumentLength, argumentName, limit));
}
internal static ArgumentException MustBeReadOnly(string argumentName)
{
return Argument(SR.GetString(SR.ADP_MustBeReadOnly, argumentName));
}
internal static InvalidOperationException InvalidMixedUsageOfSecureAndClearCredential()
{
return InvalidOperation(SR.GetString(SR.ADP_InvalidMixedUsageOfSecureAndClearCredential));
}
internal static ArgumentException InvalidMixedArgumentOfSecureAndClearCredential()
{
return Argument(SR.GetString(SR.ADP_InvalidMixedUsageOfSecureAndClearCredential));
}
internal static InvalidOperationException InvalidMixedUsageOfSecureCredentialAndIntegratedSecurity()
{
return InvalidOperation(SR.GetString(SR.ADP_InvalidMixedUsageOfSecureCredentialAndIntegratedSecurity));
}
internal static ArgumentException InvalidMixedArgumentOfSecureCredentialAndIntegratedSecurity()
{
return Argument(SR.GetString(SR.ADP_InvalidMixedUsageOfSecureCredentialAndIntegratedSecurity));
}
}
}
}

View File

@@ -2,176 +2,15 @@
// 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;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Transactions;
namespace System.Data.ProviderBase
{
abstract internal class DbConnectionClosed : DbConnectionInternal
internal abstract partial class DbConnectionClosed : DbConnectionInternal
{
// Construct an "empty" connection
protected DbConnectionClosed(ConnectionState state, bool hidePassword, bool allowSetConnectionString) : base(state, hidePassword, allowSetConnectionString)
{
}
protected override void Activate(Transaction transaction) => throw ADP.ClosedConnectionError();
public override string ServerVersion
{
get
{
throw ADP.ClosedConnectionError();
}
}
protected override void Activate(Transaction transaction)
{
throw ADP.ClosedConnectionError();
}
public override DbTransaction BeginTransaction(IsolationLevel il)
{
throw ADP.ClosedConnectionError();
}
public override void ChangeDatabase(string database)
{
throw ADP.ClosedConnectionError();
}
internal override void CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory)
{
// not much to do here...
}
protected override void Deactivate()
{
throw ADP.ClosedConnectionError();
}
public override void EnlistTransaction(Transaction transaction)
{
throw ADP.ClosedConnectionError();
}
protected override DbReferenceCollection CreateReferenceCollection()
{
throw ADP.ClosedConnectionError();
}
internal override bool TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
{
return base.TryOpenConnectionInternal(outerConnection, connectionFactory, retry, userOptions);
}
}
abstract internal class DbConnectionBusy : DbConnectionClosed
{
protected DbConnectionBusy(ConnectionState state) : base(state, true, false)
{
}
internal override bool TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
{
throw ADP.ConnectionAlreadyOpen(State);
}
}
sealed internal class DbConnectionClosedBusy : DbConnectionBusy
{
// Closed Connection, Currently Busy - changing connection string
internal static readonly DbConnectionInternal SingletonInstance = new DbConnectionClosedBusy(); // singleton object
private DbConnectionClosedBusy() : base(ConnectionState.Closed)
{
}
}
sealed internal class DbConnectionOpenBusy : DbConnectionBusy
{
// Open Connection, Currently Busy - closing connection
internal static readonly DbConnectionInternal SingletonInstance = new DbConnectionOpenBusy(); // singleton object
private DbConnectionOpenBusy() : base(ConnectionState.Open)
{
}
}
sealed internal class DbConnectionClosedConnecting : DbConnectionBusy
{
// Closed Connection, Currently Connecting
internal static readonly DbConnectionInternal SingletonInstance = new DbConnectionClosedConnecting(); // singleton object
private DbConnectionClosedConnecting() : base(ConnectionState.Connecting)
{
}
internal override void CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory)
{
connectionFactory.SetInnerConnectionTo(owningObject, DbConnectionClosedPreviouslyOpened.SingletonInstance);
}
internal override bool TryReplaceConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
{
return TryOpenConnection(outerConnection, connectionFactory, retry, userOptions);
}
internal override bool TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
{
if (retry == null || !retry.Task.IsCompleted)
{
// retry is null if this is a synchronous call
// if someone calls Open or OpenAsync while in this state,
// then the retry task will not be completed
throw ADP.ConnectionAlreadyOpen(State);
}
// we are completing an asynchronous open
Debug.Assert(retry.Task.Status == TaskStatus.RanToCompletion, "retry task must be completed successfully");
DbConnectionInternal openConnection = retry.Task.Result;
if (null == openConnection)
{
connectionFactory.SetInnerConnectionTo(outerConnection, this);
throw ADP.InternalConnectionError(ADP.ConnectionError.GetConnectionReturnsNull);
}
connectionFactory.SetInnerConnectionEvent(outerConnection, openConnection);
return true;
}
}
sealed internal class DbConnectionClosedNeverOpened : DbConnectionClosed
{
// Closed Connection, Has Never Been Opened
internal static readonly DbConnectionInternal SingletonInstance = new DbConnectionClosedNeverOpened(); // singleton object
private DbConnectionClosedNeverOpened() : base(ConnectionState.Closed, false, true)
{
}
}
sealed internal class DbConnectionClosedPreviouslyOpened : DbConnectionClosed
{
// Closed Connection, Has Previously Been Opened
internal static readonly DbConnectionInternal SingletonInstance = new DbConnectionClosedPreviouslyOpened(); // singleton object
private DbConnectionClosedPreviouslyOpened() : base(ConnectionState.Closed, true, true)
{
}
internal override bool TryReplaceConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
{
return TryOpenConnection(outerConnection, connectionFactory, retry, userOptions);
}
public override void EnlistTransaction(Transaction transaction) => throw ADP.ClosedConnectionError();
}
}

View File

@@ -2,11 +2,6 @@
// 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.Collections.Generic;
using System.Diagnostics;
using System.Data.Common;
using System.Threading;
@@ -14,141 +9,8 @@ using System.Threading.Tasks;
namespace System.Data.ProviderBase
{
internal abstract class DbConnectionFactory
internal abstract partial class DbConnectionFactory
{
private Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup> _connectionPoolGroups;
private readonly List<DbConnectionPool> _poolsToRelease;
private readonly List<DbConnectionPoolGroup> _poolGroupsToRelease;
private readonly Timer _pruningTimer;
private const int PruningDueTime = 4 * 60 * 1000; // 4 minutes
private const int PruningPeriod = 30 * 1000; // thirty seconds
// s_pendingOpenNonPooled is an array of tasks used to throttle creation of non-pooled connections to
// a maximum of Environment.ProcessorCount at a time.
private static uint s_pendingOpenNonPooledNext = 0;
private static Task<DbConnectionInternal>[] s_pendingOpenNonPooled = new Task<DbConnectionInternal>[Environment.ProcessorCount];
private static Task<DbConnectionInternal> s_completedTask;
protected DbConnectionFactory()
{
_connectionPoolGroups = new Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup>();
_poolsToRelease = new List<DbConnectionPool>();
_poolGroupsToRelease = new List<DbConnectionPoolGroup>();
_pruningTimer = CreatePruningTimer();
}
abstract public DbProviderFactory ProviderFactory
{
get;
}
public void ClearAllPools()
{
Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup> connectionPoolGroups = _connectionPoolGroups;
foreach (KeyValuePair<DbConnectionPoolKey, DbConnectionPoolGroup> entry in connectionPoolGroups)
{
DbConnectionPoolGroup poolGroup = entry.Value;
if (null != poolGroup)
{
poolGroup.Clear();
}
}
}
public void ClearPool(DbConnection connection)
{
ADP.CheckArgumentNull(connection, nameof(connection));
DbConnectionPoolGroup poolGroup = GetConnectionPoolGroup(connection);
if (null != poolGroup)
{
poolGroup.Clear();
}
}
public void ClearPool(DbConnectionPoolKey key)
{
Debug.Assert(key != null, "key cannot be null");
ADP.CheckArgumentNull(key.ConnectionString, nameof(key) + "." + nameof(key.ConnectionString));
DbConnectionPoolGroup poolGroup;
Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup> connectionPoolGroups = _connectionPoolGroups;
if (connectionPoolGroups.TryGetValue(key, out poolGroup))
{
poolGroup.Clear();
}
}
internal virtual DbConnectionPoolProviderInfo CreateConnectionPoolProviderInfo(DbConnectionOptions connectionOptions)
{
return null;
}
internal DbConnectionInternal CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
{
Debug.Assert(null != owningConnection, "null owningConnection?");
Debug.Assert(null != poolGroup, "null poolGroup?");
DbConnectionOptions connectionOptions = poolGroup.ConnectionOptions;
DbConnectionPoolGroupProviderInfo poolGroupProviderInfo = poolGroup.ProviderInfo;
DbConnectionPoolKey poolKey = poolGroup.PoolKey;
DbConnectionInternal newConnection = CreateConnection(connectionOptions, poolKey, poolGroupProviderInfo, null, owningConnection, userOptions);
if (null != newConnection)
{
newConnection.MakeNonPooledObject(owningConnection);
}
return newConnection;
}
internal DbConnectionInternal CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
{
Debug.Assert(null != pool, "null pool?");
DbConnectionPoolGroupProviderInfo poolGroupProviderInfo = pool.PoolGroup.ProviderInfo;
DbConnectionInternal newConnection = CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningObject, userOptions);
if (null != newConnection)
{
newConnection.MakePooledConnection(pool);
}
return newConnection;
}
virtual internal DbConnectionPoolGroupProviderInfo CreateConnectionPoolGroupProviderInfo(DbConnectionOptions connectionOptions)
{
return null;
}
private Timer CreatePruningTimer()
{
TimerCallback callback = new TimerCallback(PruneConnectionPoolGroups);
return new Timer(callback, null, PruningDueTime, PruningPeriod);
}
protected DbConnectionOptions FindConnectionOptions(DbConnectionPoolKey key)
{
Debug.Assert(key != null, "key cannot be null");
if (!string.IsNullOrEmpty(key.ConnectionString))
{
DbConnectionPoolGroup connectionPoolGroup;
Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup> connectionPoolGroups = _connectionPoolGroups;
if (connectionPoolGroups.TryGetValue(key, out connectionPoolGroup))
{
return connectionPoolGroup.ConnectionOptions;
}
}
return null;
}
private static Task<DbConnectionInternal> GetCompletedTask()
{
Debug.Assert(Monitor.IsEntered(s_pendingOpenNonPooled), $"Expected {nameof(s_pendingOpenNonPooled)} lock to be held.");
return s_completedTask ?? (s_completedTask = Task.FromResult<DbConnectionInternal>(null));
}
internal bool TryGetConnection(DbConnection owningConnection, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, out DbConnectionInternal connection)
{
@@ -320,283 +182,5 @@ namespace System.Data.ProviderBase
return true;
}
private DbConnectionPool GetConnectionPool(DbConnection owningObject, DbConnectionPoolGroup connectionPoolGroup)
{
// if poolgroup is disabled, it will be replaced with a new entry
Debug.Assert(null != owningObject, "null owningObject?");
Debug.Assert(null != connectionPoolGroup, "null connectionPoolGroup?");
// It is possible that while the outer connection object has
// been sitting around in a closed and unused state in some long
// running app, the pruner may have come along and remove this
// the pool entry from the master list. If we were to use a
// pool entry in this state, we would create "unmanaged" pools,
// which would be bad. To avoid this problem, we automagically
// re-create the pool entry whenever it's disabled.
// however, don't rebuild connectionOptions if no pooling is involved - let new connections do that work
if (connectionPoolGroup.IsDisabled && (null != connectionPoolGroup.PoolGroupOptions))
{
// reusing existing pool option in case user originally used SetConnectionPoolOptions
DbConnectionPoolGroupOptions poolOptions = connectionPoolGroup.PoolGroupOptions;
// get the string to hash on again
DbConnectionOptions connectionOptions = connectionPoolGroup.ConnectionOptions;
Debug.Assert(null != connectionOptions, "prevent expansion of connectionString");
connectionPoolGroup = GetConnectionPoolGroup(connectionPoolGroup.PoolKey, poolOptions, ref connectionOptions);
Debug.Assert(null != connectionPoolGroup, "null connectionPoolGroup?");
SetConnectionPoolGroup(owningObject, connectionPoolGroup);
}
DbConnectionPool connectionPool = connectionPoolGroup.GetConnectionPool(this);
return connectionPool;
}
internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, ref DbConnectionOptions userConnectionOptions)
{
if (string.IsNullOrEmpty(key.ConnectionString))
{
return (DbConnectionPoolGroup)null;
}
DbConnectionPoolGroup connectionPoolGroup;
Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup> connectionPoolGroups = _connectionPoolGroups;
if (!connectionPoolGroups.TryGetValue(key, out connectionPoolGroup) || (connectionPoolGroup.IsDisabled && (null != connectionPoolGroup.PoolGroupOptions)))
{
// If we can't find an entry for the connection string in
// our collection of pool entries, then we need to create a
// new pool entry and add it to our collection.
DbConnectionOptions connectionOptions = CreateConnectionOptions(key.ConnectionString, userConnectionOptions);
if (null == connectionOptions)
{
throw ADP.InternalConnectionError(ADP.ConnectionError.ConnectionOptionsMissing);
}
if (null == userConnectionOptions)
{ // we only allow one expansion on the connection string
userConnectionOptions = connectionOptions;
}
// We don't support connection pooling on Win9x
if (null == poolOptions)
{
if (null != connectionPoolGroup)
{
// reusing existing pool option in case user originally used SetConnectionPoolOptions
poolOptions = connectionPoolGroup.PoolGroupOptions;
}
else
{
// Note: may return null for non-pooled connections
poolOptions = CreateConnectionPoolGroupOptions(connectionOptions);
}
}
lock (this)
{
connectionPoolGroups = _connectionPoolGroups;
if (!connectionPoolGroups.TryGetValue(key, out connectionPoolGroup))
{
DbConnectionPoolGroup newConnectionPoolGroup = new DbConnectionPoolGroup(connectionOptions, key, poolOptions);
newConnectionPoolGroup.ProviderInfo = CreateConnectionPoolGroupProviderInfo(connectionOptions);
// build new dictionary with space for new connection string
Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup> newConnectionPoolGroups = new Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup>(1 + connectionPoolGroups.Count);
foreach (KeyValuePair<DbConnectionPoolKey, DbConnectionPoolGroup> entry in connectionPoolGroups)
{
newConnectionPoolGroups.Add(entry.Key, entry.Value);
}
// lock prevents race condition with PruneConnectionPoolGroups
newConnectionPoolGroups.Add(key, newConnectionPoolGroup);
connectionPoolGroup = newConnectionPoolGroup;
_connectionPoolGroups = newConnectionPoolGroups;
}
else
{
Debug.Assert(!connectionPoolGroup.IsDisabled, "Disabled pool entry discovered");
}
}
Debug.Assert(null != connectionPoolGroup, "how did we not create a pool entry?");
Debug.Assert(null != userConnectionOptions, "how did we not have user connection options?");
}
else if (null == userConnectionOptions)
{
userConnectionOptions = connectionPoolGroup.ConnectionOptions;
}
return connectionPoolGroup;
}
private void PruneConnectionPoolGroups(object state)
{
// First, walk the pool release list and attempt to clear each
// pool, when the pool is finally empty, we dispose of it. If the
// pool isn't empty, it's because there are active connections or
// distributed transactions that need it.
lock (_poolsToRelease)
{
if (0 != _poolsToRelease.Count)
{
DbConnectionPool[] poolsToRelease = _poolsToRelease.ToArray();
foreach (DbConnectionPool pool in poolsToRelease)
{
if (null != pool)
{
pool.Clear();
if (0 == pool.Count)
{
_poolsToRelease.Remove(pool);
}
}
}
}
}
// Next, walk the pool entry release list and dispose of each
// pool entry when it is finally empty. If the pool entry isn't
// empty, it's because there are active pools that need it.
lock (_poolGroupsToRelease)
{
if (0 != _poolGroupsToRelease.Count)
{
DbConnectionPoolGroup[] poolGroupsToRelease = _poolGroupsToRelease.ToArray();
foreach (DbConnectionPoolGroup poolGroup in poolGroupsToRelease)
{
if (null != poolGroup)
{
int poolsLeft = poolGroup.Clear(); // may add entries to _poolsToRelease
if (0 == poolsLeft)
{
_poolGroupsToRelease.Remove(poolGroup);
}
}
}
}
}
// Finally, we walk through the collection of connection pool entries
// and prune each one. This will cause any empty pools to be put
// into the release list.
lock (this)
{
Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup> connectionPoolGroups = _connectionPoolGroups;
Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup> newConnectionPoolGroups = new Dictionary<DbConnectionPoolKey, DbConnectionPoolGroup>(connectionPoolGroups.Count);
foreach (KeyValuePair<DbConnectionPoolKey, DbConnectionPoolGroup> entry in connectionPoolGroups)
{
if (null != entry.Value)
{
Debug.Assert(!entry.Value.IsDisabled, "Disabled pool entry discovered");
// entries start active and go idle during prune if all pools are gone
// move idle entries from last prune pass to a queue for pending release
// otherwise process entry which may move it from active to idle
if (entry.Value.Prune())
{ // may add entries to _poolsToRelease
QueuePoolGroupForRelease(entry.Value);
}
else
{
newConnectionPoolGroups.Add(entry.Key, entry.Value);
}
}
}
_connectionPoolGroups = newConnectionPoolGroups;
}
}
internal void QueuePoolForRelease(DbConnectionPool pool, bool clearing)
{
// Queue the pool up for release -- we'll clear it out and dispose
// of it as the last part of the pruning timer callback so we don't
// do it with the pool entry or the pool collection locked.
Debug.Assert(null != pool, "null pool?");
// set the pool to the shutdown state to force all active
// connections to be automatically disposed when they
// are returned to the pool
pool.Shutdown();
lock (_poolsToRelease)
{
if (clearing)
{
pool.Clear();
}
_poolsToRelease.Add(pool);
}
}
internal void QueuePoolGroupForRelease(DbConnectionPoolGroup poolGroup)
{
Debug.Assert(null != poolGroup, "null poolGroup?");
lock (_poolGroupsToRelease)
{
_poolGroupsToRelease.Add(poolGroup);
}
}
virtual protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
{
return CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningConnection);
}
internal DbMetaDataFactory GetMetaDataFactory(DbConnectionPoolGroup connectionPoolGroup, DbConnectionInternal internalConnection)
{
Debug.Assert(connectionPoolGroup != null, "connectionPoolGroup may not be null.");
// get the matadatafactory from the pool entry. If it does not already have one
// create one and save it on the pool entry
DbMetaDataFactory metaDataFactory = connectionPoolGroup.MetaDataFactory;
// consider serializing this so we don't construct multiple metadata factories
// if two threads happen to hit this at the same time. One will be GC'd
if (metaDataFactory == null)
{
bool allowCache = false;
metaDataFactory = CreateMetaDataFactory(internalConnection, out allowCache);
if (allowCache)
{
connectionPoolGroup.MetaDataFactory = metaDataFactory;
}
}
return metaDataFactory;
}
protected virtual DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory)
{
// providers that support GetSchema must override this with a method that creates a meta data
// factory appropriate for them.
cacheMetaDataFactory = false;
throw ADP.NotSupported();
}
abstract protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection);
abstract protected DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous);
abstract protected DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions(DbConnectionOptions options);
abstract internal DbConnectionPoolGroup GetConnectionPoolGroup(DbConnection connection);
abstract internal DbConnectionInternal GetInnerConnection(DbConnection connection);
abstract internal void PermissionDemand(DbConnection outerConnection);
abstract internal void SetConnectionPoolGroup(DbConnection outerConnection, DbConnectionPoolGroup poolGroup);
abstract internal void SetInnerConnectionEvent(DbConnection owningObject, DbConnectionInternal to);
abstract internal bool SetInnerConnectionFrom(DbConnection owningObject, DbConnectionInternal to, DbConnectionInternal from);
abstract internal void SetInnerConnectionTo(DbConnection owningObject, DbConnectionInternal to);
}
}

View File

@@ -3,40 +3,18 @@
// See the LICENSE file in the project root for more information.
//------------------------------------------------------------------------------
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
namespace System.Data.ProviderBase
{
internal abstract class DbConnectionInternal
internal abstract partial class DbConnectionInternal
{
internal static readonly StateChangeEventArgs StateChangeClosed = new StateChangeEventArgs(ConnectionState.Open, ConnectionState.Closed);
internal static readonly StateChangeEventArgs StateChangeOpen = new StateChangeEventArgs(ConnectionState.Closed, ConnectionState.Open);
private readonly bool _allowSetConnectionString;
private readonly bool _hidePassword;
private readonly ConnectionState _state;
private readonly WeakReference _owningObject = new WeakReference(null, false); // [usage must be thread safe] the owning object, when not in the pool. (both Pooled and Non-Pooled connections)
private DbConnectionPool _connectionPool; // the pooler that the connection came from (Pooled connections only)
private DbReferenceCollection _referenceCollection; // collection of objects that we need to notify in some way when we're being deactivated
private int _pooledCount; // [usage must be thread safe] the number of times this object has been pushed into the pool less the number of times it's been popped (0 != inPool)
private bool _connectionIsDoomed; // true when the connection should no longer be used.
private bool _cannotBePooled; // true when the connection should no longer be pooled.
private bool _isInStasis;
private DateTime _createTime; // when the connection was created.
private Transaction _enlistedTransaction; // [usage must be thread-safe] the transaction that we're enlisted in, either manually or automatically
// _enlistedTransaction is a clone, so that transaction information can be queried even if the original transaction object is disposed.
@@ -45,39 +23,6 @@ namespace System.Data.ProviderBase
// Also, this reference should not be disposed, since we aren't taking ownership of it.
private Transaction _enlistedTransactionOriginal;
#if DEBUG
private int _activateCount; // debug only counter to verify activate/deactivates are in sync.
#endif //DEBUG
protected DbConnectionInternal() : this(ConnectionState.Open, true, false)
{
}
// Constructor for internal connections
internal DbConnectionInternal(ConnectionState state, bool hidePassword, bool allowSetConnectionString)
{
_allowSetConnectionString = allowSetConnectionString;
_hidePassword = hidePassword;
_state = state;
}
internal bool AllowSetConnectionString
{
get
{
return _allowSetConnectionString;
}
}
internal bool CanBePooled
{
get
{
bool flag = (!_connectionIsDoomed && !_cannotBePooled && !_owningObject.IsAlive);
return flag;
}
}
protected internal Transaction EnlistedTransaction
{
get
@@ -237,74 +182,6 @@ namespace System.Data.ProviderBase
}
}
protected internal bool IsConnectionDoomed
{
get
{
return _connectionIsDoomed;
}
}
internal bool IsEmancipated
{
get
{
// NOTE: There are race conditions between PrePush, PostPop and this
// property getter -- only use this while this object is locked;
// (DbConnectionPool.Clear and ReclaimEmancipatedObjects
// do this for us)
// The functionality is as follows:
//
// _pooledCount is incremented when the connection is pushed into the pool
// _pooledCount is decremented when the connection is popped from the pool
// _pooledCount is set to -1 when the connection is not pooled (just in case...)
//
// That means that:
//
// _pooledCount > 1 connection is in the pool multiple times (This should not happen)
// _pooledCount == 1 connection is in the pool
// _pooledCount == 0 connection is out of the pool
// _pooledCount == -1 connection is not a pooled connection; we shouldn't be here for non-pooled connections.
// _pooledCount < -1 connection out of the pool multiple times
//
// Now, our job is to return TRUE when the connection is out
// of the pool and it's owning object is no longer around to
// return it.
bool value = (_pooledCount < 1) && !_owningObject.IsAlive;
return value;
}
}
internal bool IsInPool
{
get
{
Debug.Assert(_pooledCount <= 1 && _pooledCount >= -1, "Pooled count for object is invalid");
return (_pooledCount == 1);
}
}
protected internal object Owner
{
// We use a weak reference to the owning object so we can identify when
// it has been garbage collected without thowing exceptions.
get
{
return _owningObject.Target;
}
}
internal DbConnectionPool Pool
{
get
{
return _connectionPool;
}
}
virtual protected bool ReadyToPrepareTransaction
{
get
@@ -313,44 +190,6 @@ namespace System.Data.ProviderBase
}
}
protected internal DbReferenceCollection ReferenceCollection
{
get
{
return _referenceCollection;
}
}
abstract public string ServerVersion
{
get;
}
// this should be abstract but until it is added to all the providers virtual will have to do
virtual public string ServerVersionNormalized
{
get
{
throw ADP.NotSupported();
}
}
public bool ShouldHidePassword
{
get
{
return _hidePassword;
}
}
public ConnectionState State
{
get
{
return _state;
}
}
abstract protected void Activate(Transaction transaction);
internal void ActivateConnection(Transaction transaction)
@@ -361,26 +200,6 @@ namespace System.Data.ProviderBase
Activate(transaction);
}
internal void AddWeakReference(object value, int tag)
{
if (null == _referenceCollection)
{
_referenceCollection = CreateReferenceCollection();
if (null == _referenceCollection)
{
throw ADP.InternalError(ADP.InternalErrorCode.CreateReferenceCollectionReturnedNull);
}
}
_referenceCollection.Add(value, tag);
}
abstract public DbTransaction BeginTransaction(IsolationLevel il);
virtual public void ChangeDatabase(string value)
{
throw ADP.MethodNotImplemented();
}
internal virtual void CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory)
{
// The implementation here is the implementation required for the
@@ -487,57 +306,6 @@ namespace System.Data.ProviderBase
}
}
virtual internal void PrepareForReplaceConnection()
{
// By default, there is no preparation required
}
virtual protected void PrepareForCloseConnection()
{
// By default, there is no preparation required
}
virtual protected object ObtainAdditionalLocksForClose()
{
return null; // no additional locks in default implementation
}
virtual protected void ReleaseAdditionalLocksForClose(object lockToken)
{
// no additional locks in default implementation
}
virtual protected DbReferenceCollection CreateReferenceCollection()
{
throw ADP.InternalError(ADP.InternalErrorCode.AttemptingToConstructReferenceCollectionOnStaticObject);
}
abstract protected void Deactivate();
internal void DeactivateConnection()
{
// Internal method called from the connection pooler so we don't expose
// the Deactivate method publicly.
#if DEBUG
int activateCount = Interlocked.Decrement(ref _activateCount);
#endif // DEBUG
if (!_connectionIsDoomed && Pool.UseLoadBalancing)
{
// If we're not already doomed, check the connection's lifetime and
// doom it if it's lifetime has elapsed.
DateTime now = DateTime.UtcNow;
if ((now.Ticks - _createTime.Ticks) > Pool.LoadBalanceTimeout.Ticks)
{
DoNotPoolThisConnection();
}
}
Deactivate();
}
virtual internal void DelegatedTransactionEnded()
{
// Called by System.Transactions when the delegated transaction has
@@ -604,188 +372,9 @@ namespace System.Data.ProviderBase
enlistedTransaction.Dispose();
}
}
protected internal void DoNotPoolThisConnection()
{
_cannotBePooled = true;
}
/// <devdoc>Ensure that this connection cannot be put back into the pool.</devdoc>
protected internal void DoomThisConnection()
{
_connectionIsDoomed = true;
}
abstract public void EnlistTransaction(Transaction transaction);
protected internal virtual DataTable GetSchema(DbConnectionFactory factory, DbConnectionPoolGroup poolGroup, DbConnection outerConnection, string collectionName, string[] restrictions)
{
Debug.Assert(outerConnection != null, "outerConnection may not be null.");
DbMetaDataFactory metaDataFactory = factory.GetMetaDataFactory(poolGroup, this);
Debug.Assert(metaDataFactory != null, "metaDataFactory may not be null.");
return metaDataFactory.GetSchema(outerConnection, collectionName, restrictions);
}
internal void MakeNonPooledObject(object owningObject)
{
// Used by DbConnectionFactory to indicate that this object IS NOT part of
// a connection pool.
_connectionPool = null;
_owningObject.Target = owningObject;
_pooledCount = -1;
}
internal void MakePooledConnection(DbConnectionPool connectionPool)
{
// Used by DbConnectionFactory to indicate that this object IS part of
// a connection pool.
_createTime = DateTime.UtcNow;
_connectionPool = connectionPool;
}
internal void NotifyWeakReference(int message)
{
DbReferenceCollection referenceCollection = ReferenceCollection;
if (null != referenceCollection)
{
referenceCollection.Notify(message);
}
}
internal virtual void OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
{
if (!TryOpenConnection(outerConnection, connectionFactory, null, null))
{
throw ADP.InternalError(ADP.InternalErrorCode.SynchronousConnectReturnedPending);
}
}
/// <devdoc>The default implementation is for the open connection objects, and
/// it simply throws. Our private closed-state connection objects
/// override this and do the correct thing.</devdoc>
// User code should either override DbConnectionInternal.Activate when it comes out of the pool
// or override DbConnectionFactory.CreateConnection when the connection is created for non-pooled connections
internal virtual bool TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
{
throw ADP.ConnectionAlreadyOpen(State);
}
internal virtual bool TryReplaceConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
{
throw ADP.MethodNotImplemented();
}
protected bool TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
{
// ?->Connecting: prevent set_ConnectionString during Open
if (connectionFactory.SetInnerConnectionFrom(outerConnection, DbConnectionClosedConnecting.SingletonInstance, this))
{
DbConnectionInternal openConnection = null;
try
{
connectionFactory.PermissionDemand(outerConnection);
if (!connectionFactory.TryGetConnection(outerConnection, retry, userOptions, this, out openConnection))
{
return false;
}
}
catch
{
// This should occur for all exceptions, even ADP.UnCatchableExceptions.
connectionFactory.SetInnerConnectionTo(outerConnection, this);
throw;
}
if (null == openConnection)
{
connectionFactory.SetInnerConnectionTo(outerConnection, this);
throw ADP.InternalConnectionError(ADP.ConnectionError.GetConnectionReturnsNull);
}
connectionFactory.SetInnerConnectionEvent(outerConnection, openConnection);
}
return true;
}
internal void PrePush(object expectedOwner)
{
// Called by DbConnectionPool when we're about to be put into it's pool, we
// take this opportunity to ensure ownership and pool counts are legit.
// IMPORTANT NOTE: You must have taken a lock on the object before
// you call this method to prevent race conditions with Clear and
// ReclaimEmancipatedObjects.
//3 // The following tests are retail assertions of things we can't allow to happen.
if (null == expectedOwner)
{
if (null != _owningObject.Target)
{
throw ADP.InternalError(ADP.InternalErrorCode.UnpooledObjectHasOwner); // new unpooled object has an owner
}
}
else if (_owningObject.Target != expectedOwner)
{
throw ADP.InternalError(ADP.InternalErrorCode.UnpooledObjectHasWrongOwner); // unpooled object has incorrect owner
}
if (0 != _pooledCount)
{
throw ADP.InternalError(ADP.InternalErrorCode.PushingObjectSecondTime); // pushing object onto stack a second time
}
_pooledCount++;
_owningObject.Target = null; // NOTE: doing this and checking for InternalError.PooledObjectHasOwner degrades the close by 2%
}
internal void PostPop(object newOwner)
{
// Called by DbConnectionPool right after it pulls this from it's pool, we
// take this opportunity to ensure ownership and pool counts are legit.
Debug.Assert(!IsEmancipated, "pooled object not in pool");
// When another thread is clearing this pool, it
// will doom all connections in this pool without prejudice which
// causes the following assert to fire, which really mucks up stress
// against checked bits. The assert is benign, so we're commenting
// it out.
//Debug.Assert(CanBePooled, "pooled object is not poolable");
// IMPORTANT NOTE: You must have taken a lock on the object before
// you call this method to prevent race conditions with Clear and
// ReclaimEmancipatedObjects.
if (null != _owningObject.Target)
{
throw ADP.InternalError(ADP.InternalErrorCode.PooledObjectHasOwner); // pooled connection already has an owner!
}
_owningObject.Target = newOwner;
_pooledCount--;
//3 // The following tests are retail assertions of things we can't allow to happen.
if (null != Pool)
{
if (0 != _pooledCount)
{
throw ADP.InternalError(ADP.InternalErrorCode.PooledObjectInPoolMoreThanOnce); // popping object off stack with multiple pooledCount
}
}
else if (-1 != _pooledCount)
{
throw ADP.InternalError(ADP.InternalErrorCode.NonPooledObjectUsedMoreThanOnce); // popping object off stack with multiple pooledCount
}
}
internal void RemoveWeakReference(object value)
{
DbReferenceCollection referenceCollection = ReferenceCollection;
if (null != referenceCollection)
{
referenceCollection.Remove(value);
}
}
// Cleanup connection's transaction-specific structures (currently used by Delegated transaction).
// This is a separate method because cleanup can be triggered in multiple ways for a delegated
// transaction.
@@ -876,16 +465,5 @@ namespace System.Data.ProviderBase
{
_isInStasis = false;
}
/// <summary>
/// When overridden in a derived class, will check if the underlying connection is still actually alive
/// </summary>
/// <param name="throwOnException">If true an exception will be thrown if the connection is dead instead of returning true\false
/// (this allows the caller to have the real reason that the connection is not alive (e.g. network error, etc))</param>
/// <returns>True if the connection is still alive, otherwise false (If not overridden, then always true)</returns>
internal virtual bool IsConnectionAlive(bool throwOnException = false)
{
return true;
}
}
}

View File

@@ -413,10 +413,7 @@ namespace System.Data.ProviderBase
_objectList = new List<DbConnectionInternal>(MaxPoolSize);
if (ADP.IsPlatformNT5)
{
_transactedConnectionPool = new TransactedConnectionPool(this);
}
_transactedConnectionPool = new TransactedConnectionPool(this); // initialize irrespective of platform
_poolCreateRequest = new WaitCallback(PoolCreateRequest); // used by CleanupCallback
_state = State.Running;
@@ -664,10 +661,12 @@ namespace System.Data.ProviderBase
ReclaimEmancipatedObjects();
}
private Timer CreateCleanupTimer()
{
return (new Timer(new TimerCallback(this.CleanupCallback), null, _cleanupWait, _cleanupWait));
}
private Timer CreateCleanupTimer() =>
ADP.UnsafeCreateTimer(
new TimerCallback(CleanupCallback),
null,
_cleanupWait,
_cleanupWait);
private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
{
@@ -728,6 +727,7 @@ namespace System.Data.ProviderBase
// timer allocation has to be done out of CER block
Timer t = new Timer(new TimerCallback(this.ErrorCallback), null, Timeout.Infinite, Timeout.Infinite);
bool timerIsNotDisposed;
try { }
finally
@@ -1373,9 +1373,19 @@ namespace System.Data.ProviderBase
{
while (NeedToReplenish)
{
// Don't specify any user options because there is no outer connection associated with the new connection
newObj = CreateObject(owningObject: null, userOptions: null, oldConnection: null);
try
{
// Don't specify any user options because there is no outer connection associated with the new connection
newObj = CreateObject(owningObject: null, userOptions: null, oldConnection: null);
}
catch
{
// Catch all the exceptions occuring during CreateObject so that they
// don't emerge as unhandled on the thread pool and don't crash applications
// The error is handled in CreateObject and surfaced to the caller of the Connection Pool
// using the ErrorEvent. Hence it is OK to swallow all exceptions here.
break;
}
// We do not need to check error flag here, since we know if
// CreateObject returned null, we are in error case.
if (null != newObj)

View File

@@ -1,313 +0,0 @@
// 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.Collections.Concurrent;
using System.Data.Common;
using System.Diagnostics;
namespace System.Data.ProviderBase
{
// set_ConnectionString calls DbConnectionFactory.GetConnectionPoolGroup
// when not found a new pool entry is created and potentially added
// DbConnectionPoolGroup starts in the Active state
// Open calls DbConnectionFactory.GetConnectionPool
// if the existing pool entry is Disabled, GetConnectionPoolGroup is called for a new entry
// DbConnectionFactory.GetConnectionPool calls DbConnectionPoolGroup.GetConnectionPool
// DbConnectionPoolGroup.GetConnectionPool will return pool for the current identity
// or null if identity is restricted or pooling is disabled or state is disabled at time of add
// state changes are Active->Active, Idle->Active
// DbConnectionFactory.PruneConnectionPoolGroups calls Prune
// which will QueuePoolForRelease on all empty pools
// and once no pools remain, change state from Active->Idle->Disabled
// Once Disabled, factory can remove its reference to the pool entry
sealed internal class DbConnectionPoolGroup
{
private readonly DbConnectionOptions _connectionOptions;
private readonly DbConnectionPoolKey _poolKey;
private readonly DbConnectionPoolGroupOptions _poolGroupOptions;
private ConcurrentDictionary<DbConnectionPoolIdentity, DbConnectionPool> _poolCollection;
private int _state; // see PoolGroupState* below
private DbConnectionPoolGroupProviderInfo _providerInfo;
private DbMetaDataFactory _metaDataFactory;
// always lock this before changing _state, we don't want to move out of the 'Disabled' state
// PoolGroupStateUninitialized = 0;
private const int PoolGroupStateActive = 1; // initial state, GetPoolGroup from cache, connection Open
private const int PoolGroupStateIdle = 2; // all pools are pruned via Clear
private const int PoolGroupStateDisabled = 4; // factory pool entry pruning method
internal DbConnectionPoolGroup(DbConnectionOptions connectionOptions, DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolGroupOptions)
{
Debug.Assert(null != connectionOptions, "null connection options");
_connectionOptions = connectionOptions;
_poolKey = key;
_poolGroupOptions = poolGroupOptions;
// always lock this object before changing state
// HybridDictionary does not create any sub-objects until add
// so it is safe to use for non-pooled connection as long as
// we check _poolGroupOptions first
_poolCollection = new ConcurrentDictionary<DbConnectionPoolIdentity, DbConnectionPool>();
_state = PoolGroupStateActive;
}
internal DbConnectionOptions ConnectionOptions
{
get
{
return _connectionOptions;
}
}
internal DbConnectionPoolKey PoolKey
{
get
{
return _poolKey;
}
}
internal DbConnectionPoolGroupProviderInfo ProviderInfo
{
get
{
return _providerInfo;
}
set
{
_providerInfo = value;
if (null != value)
{
_providerInfo.PoolGroup = this;
}
}
}
internal bool IsDisabled
{
get
{
return (PoolGroupStateDisabled == _state);
}
}
internal DbConnectionPoolGroupOptions PoolGroupOptions
{
get
{
return _poolGroupOptions;
}
}
internal DbMetaDataFactory MetaDataFactory
{
get
{
return _metaDataFactory;
}
set
{
_metaDataFactory = value;
}
}
internal int Clear()
{
// must be multi-thread safe with competing calls by Clear and Prune via background thread
// will return the number of connections in the group after clearing has finished
// First, note the old collection and create a new collection to be used
ConcurrentDictionary<DbConnectionPoolIdentity, DbConnectionPool> oldPoolCollection = null;
lock (this)
{
if (_poolCollection.Count > 0)
{
oldPoolCollection = _poolCollection;
_poolCollection = new ConcurrentDictionary<DbConnectionPoolIdentity, DbConnectionPool>();
}
}
// Then, if a new collection was created, release the pools from the old collection
if (oldPoolCollection != null)
{
foreach (var entry in oldPoolCollection)
{
DbConnectionPool pool = entry.Value;
if (pool != null)
{
DbConnectionFactory connectionFactory = pool.ConnectionFactory;
connectionFactory.QueuePoolForRelease(pool, true);
}
}
}
// Finally, return the pool collection count - this may be non-zero if something was added while we were clearing
return _poolCollection.Count;
}
internal DbConnectionPool GetConnectionPool(DbConnectionFactory connectionFactory)
{
// When this method returns null it indicates that the connection
// factory should not use pooling.
// We don't support connection pooling on Win9x;
// PoolGroupOptions will only be null when we're not supposed to pool
// connections.
DbConnectionPool pool = null;
if (null != _poolGroupOptions)
{
DbConnectionPoolIdentity currentIdentity = DbConnectionPoolIdentity.NoIdentity;
if (_poolGroupOptions.PoolByIdentity)
{
// if we're pooling by identity (because integrated security is
// being used for these connections) then we need to go out and
// search for the connectionPool that matches the current identity.
currentIdentity = DbConnectionPoolIdentity.GetCurrent();
// If the current token is restricted in some way, then we must
// not attempt to pool these connections.
if (currentIdentity.IsRestricted)
{
currentIdentity = null;
}
}
if (null != currentIdentity)
{
if (!_poolCollection.TryGetValue(currentIdentity, out pool)) // find the pool
{
lock (this)
{
// Did someone already add it to the list?
if (!_poolCollection.TryGetValue(currentIdentity, out pool))
{
DbConnectionPoolProviderInfo connectionPoolProviderInfo = connectionFactory.CreateConnectionPoolProviderInfo(this.ConnectionOptions);
DbConnectionPool newPool = new DbConnectionPool(connectionFactory, this, currentIdentity, connectionPoolProviderInfo);
if (MarkPoolGroupAsActive())
{
// If we get here, we know for certain that we there isn't
// a pool that matches the current identity, so we have to
// add the optimistically created one
newPool.Startup(); // must start pool before usage
bool addResult = _poolCollection.TryAdd(currentIdentity, newPool);
Debug.Assert(addResult, "No other pool with current identity should exist at this point");
pool = newPool;
}
else
{
// else pool entry has been disabled so don't create new pools
Debug.Assert(PoolGroupStateDisabled == _state, "state should be disabled");
// don't need to call connectionFactory.QueuePoolForRelease(newPool) because
// pool callbacks were delayed and no risk of connections being created
newPool.Shutdown();
}
}
else
{
// else found an existing pool to use instead
Debug.Assert(PoolGroupStateActive == _state, "state should be active since a pool exists and lock holds");
}
}
}
// the found pool could be in any state
}
}
if (null == pool)
{
lock (this)
{
// keep the pool entry state active when not pooling
MarkPoolGroupAsActive();
}
}
return pool;
}
private bool MarkPoolGroupAsActive()
{
// when getting a connection, make the entry active if it was idle (but not disabled)
// must always lock this before calling
if (PoolGroupStateIdle == _state)
{
_state = PoolGroupStateActive;
}
return (PoolGroupStateActive == _state);
}
internal bool Prune()
{
// must only call from DbConnectionFactory.PruneConnectionPoolGroups on background timer thread
// must lock(DbConnectionFactory._connectionPoolGroups.SyncRoot) before calling ReadyToRemove
// to avoid conflict with DbConnectionFactory.CreateConnectionPoolGroup replacing pool entry
lock (this)
{
if (_poolCollection.Count > 0)
{
var newPoolCollection = new ConcurrentDictionary<DbConnectionPoolIdentity, DbConnectionPool>();
foreach (var entry in _poolCollection)
{
DbConnectionPool pool = entry.Value;
if (pool != null)
{
// Actually prune the pool if there are no connections in the pool and no errors occurred.
// Empty pool during pruning indicates zero or low activity, but
// an error state indicates the pool needs to stay around to
// throttle new connection attempts.
if ((!pool.ErrorOccurred) && (0 == pool.Count))
{
// Order is important here. First we remove the pool
// from the collection of pools so no one will try
// to use it while we're processing and finally we put the
// pool into a list of pools to be released when they
// are completely empty.
DbConnectionFactory connectionFactory = pool.ConnectionFactory;
connectionFactory.QueuePoolForRelease(pool, false);
}
else
{
newPoolCollection.TryAdd(entry.Key, entry.Value);
}
}
}
_poolCollection = newPoolCollection;
}
// must be pruning thread to change state and no connections
// otherwise pruning thread risks making entry disabled soon after user calls ClearPool
if (0 == _poolCollection.Count)
{
if (PoolGroupStateActive == _state)
{
_state = PoolGroupStateIdle;
}
else if (PoolGroupStateIdle == _state)
{
_state = PoolGroupStateDisabled;
}
}
return (PoolGroupStateDisabled == _state);
}
}
}
}

View File

@@ -1,286 +0,0 @@
// 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.Threading;
namespace System.Data.ProviderBase
{
internal abstract class DbReferenceCollection
{
private struct CollectionEntry
{
private int _tag; // information about the reference
private WeakReference _weak; // the reference itself.
public void NewTarget(int tag, object target)
{
Debug.Assert(!HasTarget, "Entry already has a valid target");
Debug.Assert(tag != 0, "Bad tag");
Debug.Assert(target != null, "Invalid target");
if (_weak == null)
{
_weak = new WeakReference(target, false);
}
else
{
_weak.Target = target;
}
_tag = tag;
}
public void RemoveTarget()
{
_tag = 0;
}
public bool HasTarget
{
get
{
return ((_tag != 0) && (_weak.IsAlive));
}
}
public int Tag
{
get
{
return _tag;
}
}
public object Target
{
get
{
return (_tag == 0 ? null : _weak.Target);
}
}
}
private const int LockPollTime = 100; // Time to wait (in ms) between attempting to get the _itemLock
private const int DefaultCollectionSize = 20; // Default size for the collection, and the amount to grow every time the collection is full
private CollectionEntry[] _items; // The collection of items we are keeping track of
private readonly object _itemLock; // Used to synchronize access to the _items collection
private int _optimisticCount; // (#ItemsAdded - #ItemsRemoved) - This estimates the number of items that we *should* have (but doesn't take into account item targets being GC'd)
private int _lastItemIndex; // Location of the last item in _items
private volatile bool _isNotifying; // Indicates that the collection is currently being notified (and, therefore, about to be cleared)
protected DbReferenceCollection()
{
_items = new CollectionEntry[DefaultCollectionSize];
_itemLock = new object();
_optimisticCount = 0;
_lastItemIndex = 0;
}
abstract public void Add(object value, int tag);
protected void AddItem(object value, int tag)
{
Debug.Assert(null != value && 0 != tag, "AddItem with null value or 0 tag");
bool itemAdded = false;
lock (_itemLock)
{
// Try to find a free spot
for (int i = 0; i <= _lastItemIndex; ++i)
{
if (_items[i].Tag == 0)
{
_items[i].NewTarget(tag, value);
Debug.Assert(_items[i].HasTarget, "missing expected target");
itemAdded = true;
break;
}
}
// No free spots, can we just add on to the end?
if ((!itemAdded) && (_lastItemIndex + 1 < _items.Length))
{
_lastItemIndex++;
_items[_lastItemIndex].NewTarget(tag, value);
itemAdded = true;
}
// If no free spots and no space at the end, try to find a dead item
if (!itemAdded)
{
for (int i = 0; i <= _lastItemIndex; ++i)
{
if (!_items[i].HasTarget)
{
_items[i].NewTarget(tag, value);
Debug.Assert(_items[i].HasTarget, "missing expected target");
itemAdded = true;
break;
}
}
}
// If nothing was free, then resize and add to the end
if (!itemAdded)
{
Array.Resize<CollectionEntry>(ref _items, _items.Length * 2);
_lastItemIndex++;
_items[_lastItemIndex].NewTarget(tag, value);
}
_optimisticCount++;
}
}
internal T FindItem<T>(int tag, Func<T, bool> filterMethod) where T : class
{
bool lockObtained = false;
try
{
TryEnterItemLock(ref lockObtained);
if (lockObtained)
{
if (_optimisticCount > 0)
{
// Loop through the items
for (int counter = 0; counter <= _lastItemIndex; counter++)
{
// Check tag (should be easiest and quickest)
if (_items[counter].Tag == tag)
{
// NOTE: Check if the returned value is null twice may seem wasteful, but this if for performance
// Since checking for null twice is cheaper than calling both HasTarget and Target OR always attempting to typecast
object value = _items[counter].Target;
if (value != null)
{
// Make sure the item has the correct type and passes the filtering
T tempItem = value as T;
if ((tempItem != null) && (filterMethod(tempItem)))
{
return tempItem;
}
}
}
}
}
}
}
finally
{
ExitItemLockIfNeeded(lockObtained);
}
// If we got to here, then no item was found, so return null
return null;
}
public void Notify(int message)
{
bool lockObtained = false;
try
{
TryEnterItemLock(ref lockObtained);
if (lockObtained)
{
try
{
_isNotifying = true;
// Loop through each live item and notify it
if (_optimisticCount > 0)
{
for (int index = 0; index <= _lastItemIndex; ++index)
{
object value = _items[index].Target; // checks tag & gets target
if (null != value)
{
NotifyItem(message, _items[index].Tag, value);
_items[index].RemoveTarget();
}
Debug.Assert(!_items[index].HasTarget, "Unexpected target after notifying");
}
_optimisticCount = 0;
}
// Shrink collection (if needed)
if (_items.Length > 100)
{
_lastItemIndex = 0;
_items = new CollectionEntry[DefaultCollectionSize];
}
}
finally
{
_isNotifying = false;
}
}
}
finally
{
ExitItemLockIfNeeded(lockObtained);
}
}
abstract protected void NotifyItem(int message, int tag, object value);
abstract public void Remove(object value);
protected void RemoveItem(object value)
{
Debug.Assert(null != value, "RemoveItem with null");
bool lockObtained = false;
try
{
TryEnterItemLock(ref lockObtained);
if (lockObtained)
{
// Find the value, and then remove the target from our collection
if (_optimisticCount > 0)
{
for (int index = 0; index <= _lastItemIndex; ++index)
{
if (value == _items[index].Target)
{ // checks tag & gets target
_items[index].RemoveTarget();
_optimisticCount--;
break;
}
}
}
}
}
finally
{
ExitItemLockIfNeeded(lockObtained);
}
}
// This is polling lock that will abandon getting the lock if _isNotifying is set to true
private void TryEnterItemLock(ref bool lockObtained)
{
// Assume that we couldn't take the lock
lockObtained = false;
// Keep trying to take the lock until either we've taken it, or the collection is being notified
while ((!_isNotifying) && (!lockObtained))
{
Monitor.TryEnter(_itemLock, LockPollTime, ref lockObtained);
}
}
private void ExitItemLockIfNeeded(bool lockObtained)
{
if (lockObtained)
{
Monitor.Exit(_itemLock);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More