From dcff145d1569f7017481851a9c0cad1104735b7c Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Mon, 13 Jan 2020 00:38:54 +0000 Subject: [PATCH 1/2] add cached SqlReferenceCollection find delegate and context objects --- .../Data/SqlClient/SqlReferenceCollection.cs | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs index efcb66cf28..0baea7724c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs @@ -2,18 +2,54 @@ // 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; using System.Diagnostics; +using System.Threading; using Microsoft.Data.ProviderBase; namespace Microsoft.Data.SqlClient { sealed internal class SqlReferenceCollection : DbReferenceCollection { + private sealed class FindLiveCommandContext + { + public readonly Func Func; + + private TdsParserStateObject _stateObj; + + public FindLiveCommandContext() => Func = Predicate; + + public void Setup(TdsParserStateObject state) => _stateObj = state; + + public void Clear() => _stateObj = null; + + private bool Predicate(SqlCommand command) => command.StateObject == _stateObj; + } + + private sealed class FindLiveReaderContext + { + public readonly Func Func; + + private SqlCommand _command; + + public FindLiveReaderContext() => Func = Predicate; + + public void Setup(SqlCommand command) => _command = command; + + public void Clear() => _command = null; + + private bool Predicate(SqlDataReader reader) => (!reader.IsClosed) && (_command == reader.Command); + } + internal const int DataReaderTag = 1; internal const int CommandTag = 2; internal const int BulkCopyTag = 3; - override public void Add(object value, int tag) + private readonly static Func s_hasOpenReaderFunc = HasOpenReaderPredicate; + private static FindLiveCommandContext s_cachedFindLiveCommandContext; + private static FindLiveReaderContext s_cachedFindLiveReaderContext; + + public override void Add(object value, int tag) { Debug.Assert(DataReaderTag == tag || CommandTag == tag || BulkCopyTag == tag, "unexpected tag?"); Debug.Assert(DataReaderTag != tag || value is SqlDataReader, "tag doesn't match object type: SqlDataReader"); @@ -30,25 +66,35 @@ internal void Deactivate() internal SqlDataReader FindLiveReader(SqlCommand command) { - if (command == null) + if (command is null) { // if null == command, will find first live datareader - return FindItem(DataReaderTag, (dataReader) => (!dataReader.IsClosed)); + return FindItem(DataReaderTag, s_hasOpenReaderFunc); } else { // else will find live datareader associated with the command - return FindItem(DataReaderTag, (dataReader) => ((!dataReader.IsClosed) && (command == dataReader.Command))); + FindLiveReaderContext context = Interlocked.Exchange(ref s_cachedFindLiveReaderContext, null) ?? new FindLiveReaderContext(); + context.Setup(command); + SqlDataReader retval = FindItem(DataReaderTag, context.Func); + context.Clear(); + Interlocked.CompareExchange(ref s_cachedFindLiveReaderContext, context, null); + return retval; } } // Finds a SqlCommand associated with the given StateObject internal SqlCommand FindLiveCommand(TdsParserStateObject stateObj) { - return FindItem(CommandTag, (command) => (command.StateObject == stateObj)); + FindLiveCommandContext context = Interlocked.Exchange(ref s_cachedFindLiveCommandContext, null) ?? new FindLiveCommandContext(); + context.Setup(stateObj); + SqlCommand retval = FindItem(CommandTag, context.Func); + context.Clear(); + Interlocked.CompareExchange(ref s_cachedFindLiveCommandContext, context, null); + return retval; } - override protected void NotifyItem(int message, int tag, object value) + protected override void NotifyItem(int message, int tag, object value) { Debug.Assert(0 == message, "unexpected message?"); Debug.Assert(DataReaderTag == tag || CommandTag == tag || BulkCopyTag == tag, "unexpected tag?"); @@ -74,11 +120,13 @@ override protected void NotifyItem(int message, int tag, object value) } } - override public void Remove(object value) + public override void Remove(object value) { Debug.Assert(value is SqlDataReader || value is SqlCommand || value is SqlBulkCopy, "SqlReferenceCollection.Remove expected a SqlDataReader or SqlCommand or SqlBulkCopy"); base.RemoveItem(value); } + + private static bool HasOpenReaderPredicate(SqlDataReader reader) => !reader.IsClosed; } } From d4638492e9704351f62940332326a2f5b2fd01c4 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Thu, 27 Feb 2020 20:50:34 +0000 Subject: [PATCH 2/2] remove unused FindLiveCommand function and support --- .../Data/SqlClient/SqlInternalConnection.cs | 11 -------- .../Data/SqlClient/SqlReferenceCollection.cs | 27 ------------------- 2 files changed, 38 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs index e5861df337..7c71dcdedb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs @@ -567,17 +567,6 @@ internal SqlDataReader FindLiveReader(SqlCommand command) return reader; } - internal SqlCommand FindLiveCommand(TdsParserStateObject stateObj) - { - SqlCommand command = null; - SqlReferenceCollection referenceCollection = (SqlReferenceCollection)ReferenceCollection; - if (null != referenceCollection) - { - command = referenceCollection.FindLiveCommand(stateObj); - } - return command; - } - abstract protected byte[] GetDTCAddress(); static private byte[] GetTransactionCookie(Transaction transaction, byte[] whereAbouts) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs index 0baea7724c..f6780b1bf4 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs @@ -11,21 +11,6 @@ namespace Microsoft.Data.SqlClient { sealed internal class SqlReferenceCollection : DbReferenceCollection { - private sealed class FindLiveCommandContext - { - public readonly Func Func; - - private TdsParserStateObject _stateObj; - - public FindLiveCommandContext() => Func = Predicate; - - public void Setup(TdsParserStateObject state) => _stateObj = state; - - public void Clear() => _stateObj = null; - - private bool Predicate(SqlCommand command) => command.StateObject == _stateObj; - } - private sealed class FindLiveReaderContext { public readonly Func Func; @@ -46,7 +31,6 @@ private sealed class FindLiveReaderContext internal const int BulkCopyTag = 3; private readonly static Func s_hasOpenReaderFunc = HasOpenReaderPredicate; - private static FindLiveCommandContext s_cachedFindLiveCommandContext; private static FindLiveReaderContext s_cachedFindLiveReaderContext; public override void Add(object value, int tag) @@ -83,17 +67,6 @@ internal SqlDataReader FindLiveReader(SqlCommand command) } } - // Finds a SqlCommand associated with the given StateObject - internal SqlCommand FindLiveCommand(TdsParserStateObject stateObj) - { - FindLiveCommandContext context = Interlocked.Exchange(ref s_cachedFindLiveCommandContext, null) ?? new FindLiveCommandContext(); - context.Setup(stateObj); - SqlCommand retval = FindItem(CommandTag, context.Func); - context.Clear(); - Interlocked.CompareExchange(ref s_cachedFindLiveCommandContext, context, null); - return retval; - } - protected override void NotifyItem(int message, int tag, object value) { Debug.Assert(0 == message, "unexpected message?");