From e0ee6ea94f835e2e5fd552c3e8d1c15a5228e396 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Wed, 13 Oct 2021 15:59:27 -0700 Subject: [PATCH 1/8] Move to shared - SqlInternalTransaction Move the file to common folder. --- .../src/Microsoft.Data.SqlClient.csproj | 4 +- .../Data/SqlClient/sqlinternaltransaction.cs | 588 ------------------ .../Data/SqlClient/SqlInternalTransaction.cs | 172 ++--- 3 files changed, 71 insertions(+), 693 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/sqlinternaltransaction.cs rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs (84%) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 4acd15dadc..664151d571 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -532,7 +532,9 @@ - + + Microsoft\Data\SqlClient\SqlInternalTransaction.cs + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/sqlinternaltransaction.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/sqlinternaltransaction.cs deleted file mode 100644 index f1f929da7b..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/sqlinternaltransaction.cs +++ /dev/null @@ -1,588 +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; -using System.Data; -using System.Diagnostics; -using System.Threading; -using Microsoft.Data.Common; - -namespace Microsoft.Data.SqlClient -{ - internal enum TransactionState - { - Pending = 0, - Active = 1, - Aborted = 2, - Committed = 3, - Unknown = 4, - } - - internal enum TransactionType - { - LocalFromTSQL = 1, - LocalFromAPI = 2, - Delegated = 3, - Distributed = 4, - Context = 5, // only valid in proc. - } - - sealed internal class SqlInternalTransaction - { - internal const long NullTransactionId = 0; - - private TransactionState _transactionState; - private TransactionType _transactionType; - private long _transactionId; // passed in the MARS headers - private int _openResultCount; // passed in the MARS headers - private SqlInternalConnection _innerConnection; - private bool _disposing; // used to prevent us from throwing exceptions while we're disposing - private WeakReference _parent; // weak ref to the outer transaction object; needs to be weak to allow GC to occur. - - private static int _objectTypeCount; // EventSource Counter - internal readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount); - - internal bool RestoreBrokenConnection { get; set; } - internal bool ConnectionHasBeenRestored { get; set; } - - internal SqlInternalTransaction(SqlInternalConnection innerConnection, TransactionType type, SqlTransaction outerTransaction) : this(innerConnection, type, outerTransaction, NullTransactionId) - { - } - - internal SqlInternalTransaction(SqlInternalConnection innerConnection, TransactionType type, SqlTransaction outerTransaction, long transactionId) - { - SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Created for connection {1}, outer transaction {2}, Type {3}", ObjectID, innerConnection.ObjectID, (null != outerTransaction) ? outerTransaction.ObjectID : -1, (int)type); - - _innerConnection = innerConnection; - _transactionType = type; - - if (null != outerTransaction) - { - _parent = new WeakReference(outerTransaction); - } - - _transactionId = transactionId; - RestoreBrokenConnection = false; - ConnectionHasBeenRestored = false; - } - - internal bool HasParentTransaction - { - get - { - // Return true if we are an API started local transaction, or if we were a TSQL - // started local transaction and were then wrapped with a parent transaction as - // a result of a later API begin transaction. - bool result = ((TransactionType.LocalFromAPI == _transactionType) || - (TransactionType.LocalFromTSQL == _transactionType && _parent != null)); - return result; - } - } - - internal bool IsAborted - { - get - { - return (TransactionState.Aborted == _transactionState); - } - } - - internal bool IsActive - { - get - { - return (TransactionState.Active == _transactionState); - } - } - - internal bool IsCommitted - { - get - { - return (TransactionState.Committed == _transactionState); - } - } - - internal bool IsCompleted - { - get - { - return (TransactionState.Aborted == _transactionState - || TransactionState.Committed == _transactionState - || TransactionState.Unknown == _transactionState); - } - } - - internal bool IsContext - { - get - { - bool result = (TransactionType.Context == _transactionType); - return result; - } - } - - internal bool IsDelegated - { - get - { - bool result = (TransactionType.Delegated == _transactionType); - return result; - } - } - - internal bool IsDistributed - { - get - { - bool result = (TransactionType.Distributed == _transactionType); - return result; - } - } - - internal bool IsLocal - { - get - { - bool result = (TransactionType.LocalFromTSQL == _transactionType - || TransactionType.LocalFromAPI == _transactionType - || TransactionType.Context == _transactionType); - return result; - } - } - - internal bool IsOrphaned - { - get - { - // An internal transaction is orphaned when its parent has been - // reclaimed by GC. - bool result; - if (null == _parent) - { - // No parent, so we better be LocalFromTSQL. Should we even return in this case - - // since it could be argued this is invalid? - Debug.Fail("Why are we calling IsOrphaned with no parent?"); - Debug.Assert(_transactionType == TransactionType.LocalFromTSQL, "invalid state"); - result = false; - } - else if (!_parent.TryGetTarget(out SqlTransaction _)) - { - // We had a parent, but parent was GC'ed. - result = true; - } - else - { - // We have a parent, and parent is alive. - result = false; - } - - return result; - } - } - - internal bool IsZombied - { - get - { - return (null == _innerConnection); - } - } - - internal int ObjectID - { - get - { - return _objectID; - } - } - - internal int OpenResultsCount - { - get - { - return _openResultCount; - } - } - - internal SqlTransaction Parent - { - get - { - SqlTransaction result = null; - // Should we protect against this, since this probably is an invalid state? - Debug.Assert(null != _parent, "Why are we calling Parent with no parent?"); - if (_parent != null && _parent.TryGetTarget(out SqlTransaction target)) - { - result = target; - } - return result; - } - } - - internal long TransactionId - { - get - { - return _transactionId; - } - set - { - Debug.Assert(NullTransactionId == _transactionId, "setting transaction cookie while one is active?"); - _transactionId = value; - } - } - - internal void Activate() - { - _transactionState = TransactionState.Active; - } - - private void CheckTransactionLevelAndZombie() - { - try - { - if (!IsZombied && GetServerTransactionLevel() == 0) - { - // If not zombied, not closed, and not in transaction, zombie. - Zombie(); - } - } - catch (Exception e) - { - // UNDONE - should not be catching all exceptions!!! - if (!ADP.IsCatchableExceptionType(e)) - { - throw; - } - - ADP.TraceExceptionWithoutRethrow(e); - Zombie(); // If exception caught when trying to check level, zombie. - } - } - - internal void CloseFromConnection() - { - SqlInternalConnection innerConnection = _innerConnection; - - Debug.Assert(innerConnection != null, "How can we be here if the connection is null?"); - SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Closing", ObjectID); - - bool processFinallyBlock = true; - try - { - innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.IfRollback, null, IsolationLevel.Unspecified, null, false); - } - catch (Exception e) - { - processFinallyBlock = ADP.IsCatchableExceptionType(e); - throw; - } - finally - { - TdsParser.ReliabilitySection.Assert("unreliable call to CloseFromConnection"); // you need to setup for a thread abort somewhere before you call this method - if (processFinallyBlock) - { - // Always ensure we're zombied; Yukon will send an EnvChange that - // will cause the zombie, but only if we actually go to the wire; - // Sphinx and Shiloh won't send the env change, so we have to handle - // them ourselves. - Zombie(); - } - } - } - - internal void Commit() - { - using (TryEventScope.Create(" {0}", ObjectID)) - { - if (_innerConnection.IsLockedForBulkCopy) - { - throw SQL.ConnectionLockedForBcpEvent(); - } - - _innerConnection.ValidateConnectionForExecute(null); - - // If this transaction has been completed, throw exception since it is unusable. - try - { - // COMMIT ignores transaction names, and so there is no reason to pass it anything. COMMIT - // simply commits the transaction from the most recent BEGIN, nested or otherwise. - _innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Commit, null, IsolationLevel.Unspecified, null, false); - - // SQL BU DT 291159 - perform full Zombie on pre-Yukon, but do not actually - // complete internal transaction until informed by server in the case of Yukon - // or later. - if (!IsZombied && !_innerConnection.IsYukonOrNewer) - { - // Since nested transactions are no longer allowed, set flag to false. - // This transaction has been completed. - Zombie(); - } - else - { - ZombieParent(); - } - } - catch (Exception e) - { - // UNDONE - should not be catching all exceptions!!! - if (ADP.IsCatchableExceptionType(e)) - { - CheckTransactionLevelAndZombie(); - } - - throw; - } - } - } - - internal void Completed(TransactionState transactionState) - { - Debug.Assert(TransactionState.Active < transactionState, "invalid transaction completion state?"); - _transactionState = transactionState; - Zombie(); - } - - internal Int32 DecrementAndObtainOpenResultCount() - { - Int32 openResultCount = Interlocked.Decrement(ref _openResultCount); - if (openResultCount < 0) - { - throw SQL.OpenResultCountExceeded(); - } - return openResultCount; - } - - internal void Dispose() - { - this.Dispose(true); - System.GC.SuppressFinalize(this); - } - - private /*protected override*/ void Dispose(bool disposing) - { - SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Disposing", ObjectID); - - if (disposing) - { - if (null != _innerConnection) - { - // implicitly rollback if transaction still valid - _disposing = true; - this.Rollback(); - } - } - } - - private int GetServerTransactionLevel() - { - // This function is needed for those times when it is impossible to determine the server's - // transaction level, unless the user's arguments were parsed - which is something we don't want - // to do. An example when it is impossible to determine the level is after a rollback. - - // TODO: we really ought to be able to execute without using the public objects... - - using (SqlCommand transactionLevelCommand = new SqlCommand("set @out = @@trancount", (SqlConnection)(_innerConnection.Owner))) - { - transactionLevelCommand.Transaction = Parent; - - SqlParameter parameter = new SqlParameter("@out", SqlDbType.Int); - parameter.Direction = ParameterDirection.Output; - transactionLevelCommand.Parameters.Add(parameter); - - // UNDONE: use a singleton select here - // UNDONE: execute without SqlClientPermission.Demand() - transactionLevelCommand.RunExecuteReader(0, RunBehavior.UntilDone, false /* returnDataStream */, nameof(GetServerTransactionLevel)); - - return (int)parameter.Value; - } - } - - internal Int32 IncrementAndObtainOpenResultCount() - { - Int32 openResultCount = Interlocked.Increment(ref _openResultCount); - - if (openResultCount < 0) - { - throw SQL.OpenResultCountExceeded(); - } - return openResultCount; - } - - internal void InitParent(SqlTransaction transaction) - { - Debug.Assert(_parent == null, "Why do we have a parent on InitParent?"); - _parent = new WeakReference(transaction); - } - - internal void Rollback() - { - using (TryEventScope.Create(" {0}", ObjectID)) - { - if (_innerConnection.IsLockedForBulkCopy) - { - throw SQL.ConnectionLockedForBcpEvent(); - } - - _innerConnection.ValidateConnectionForExecute(null); - - try - { - // If no arg is given to ROLLBACK it will rollback to the outermost begin - rolling back - // all nested transactions as well as the outermost transaction. - _innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.IfRollback, null, IsolationLevel.Unspecified, null, false); - - // Since Rollback will rollback to outermost begin, no need to check - // server transaction level. This transaction has been completed. - Zombie(); - } - catch (Exception e) - { - // UNDONE - should not be catching all exceptions!!! - if (ADP.IsCatchableExceptionType(e)) - { - CheckTransactionLevelAndZombie(); - - if (!_disposing) - { - throw; - } - } - else - { - throw; - } - } - } - } - - internal void Rollback(string transactionName) - { - using (TryEventScope.Create(" {0}, transactionName='{1}'", ObjectID, transactionName)) - { - if (_innerConnection.IsLockedForBulkCopy) - { - throw SQL.ConnectionLockedForBcpEvent(); - } - - _innerConnection.ValidateConnectionForExecute(null); - - // ROLLBACK takes either a save point name or a transaction name. It will rollback the - // transaction to either the save point with the save point name or begin with the - // transaction name. NOTE: for simplicity it is possible to give all save point names - // the same name, and ROLLBACK will simply rollback to the most recent save point with the - // save point name. - if (ADP.IsEmpty(transactionName)) - { - throw SQL.NullEmptyTransactionName(); - } - - try - { - _innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Rollback, transactionName, IsolationLevel.Unspecified, null, false); - - if (!IsZombied && !_innerConnection.IsYukonOrNewer) - { - // Check if Zombied before making round-trip to server. - // Against Yukon we receive an envchange on the ExecuteTransaction above on the - // parser that calls back into SqlTransaction for the Zombie() call. - CheckTransactionLevelAndZombie(); - } - } - catch (Exception e) - { - // UNDONE - should not be catching all exceptions!!! - if (ADP.IsCatchableExceptionType(e)) - { - CheckTransactionLevelAndZombie(); - } - throw; - } - } - } - - internal void Save(string savePointName) - { - using (TryEventScope.Create(" {0}, savePointName='{1}'", ObjectID, savePointName)) - { - _innerConnection.ValidateConnectionForExecute(null); - - // ROLLBACK takes either a save point name or a transaction name. It will rollback the - // transaction to either the save point with the save point name or begin with the - // transaction name. So, to rollback a nested transaction you must have a save point. - // SAVE TRANSACTION MUST HAVE AN ARGUMENT!!! Save Transaction without an arg throws an - // exception from the server. So, an overload for SaveTransaction without an arg doesn't make - // sense to have. Save Transaction does not affect the transaction level. - if (ADP.IsEmpty(savePointName)) - { - throw SQL.NullEmptyTransactionName(); - } - - try - { - _innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Save, savePointName, IsolationLevel.Unspecified, null, false); - } - catch (Exception e) - { - // UNDONE - should not be catching all exceptions!!! - if (ADP.IsCatchableExceptionType(e)) - { - CheckTransactionLevelAndZombie(); - } - - throw; - } - } - } - - internal void Zombie() - { - // Called by several places in the code to ensure that the outer - // transaction object has been zombied and the parser has broken - // it's reference to us. - - // NOTE: we'll be called from the TdsParser when it gets appropriate - // ENVCHANGE events that indicate the transaction has completed, however - // we cannot rely upon those events occuring in the case of pre-Yukon - // servers (and when we don't go to the wire because the connection - // is broken) so we can also be called from the Commit/Rollback/Save - // methods to handle that case as well. - - // There are two parts to a full zombie: - // 1) Zombie parent and disconnect outer transaction from internal transaction - // 2) Disconnect internal transaction from connection and parser - // Number 1 needs to be done whenever a SqlTransaction object is completed. Number - // 2 is only done when a transaction is actually completed. Since users can begin - // transactions both in and outside of the API, and since nested begins are not actual - // transactions we need to distinguish between #1 and #2. See SQL BU DT 291159 - // for further details. - - ZombieParent(); - - SqlInternalConnection innerConnection = _innerConnection; - _innerConnection = null; - - if (null != innerConnection) - { - innerConnection.DisconnectTransaction(this); - } - } - - private void ZombieParent() - { - if (_parent != null && _parent.TryGetTarget(out SqlTransaction parent)) - { - parent.Zombie(); - } - _parent = null; - } - - internal string TraceString() - { - return string.Format(/*IFormatProvider*/ null, "(ObjId={0}, tranId={1}, state={2}, type={3}, open={4}, disp={5}", - ObjectID, _transactionId, _transactionState, _transactionType, _openResultCount, _disposing); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs similarity index 84% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs index 408dba0645..4064149dd4 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs @@ -66,81 +66,34 @@ internal SqlInternalTransaction(SqlInternalConnection innerConnection, Transacti ConnectionHasBeenRestored = false; } - internal bool HasParentTransaction - { - get - { + internal bool HasParentTransaction => // Return true if we are an API started local transaction, or if we were a TSQL // started local transaction and were then wrapped with a parent transaction as // a result of a later API begin transaction. - bool result = ((TransactionType.LocalFromAPI == _transactionType) || - (TransactionType.LocalFromTSQL == _transactionType && _parent != null)); - return result; - } - } + (TransactionType.LocalFromAPI == _transactionType) || + (TransactionType.LocalFromTSQL == _transactionType && _parent != null); - internal bool IsAborted - { - get - { - return (TransactionState.Aborted == _transactionState); - } - } + internal bool IsAborted => TransactionState.Aborted == _transactionState; - internal bool IsActive - { - get - { - return (TransactionState.Active == _transactionState); - } - } + internal bool IsActive => TransactionState.Active == _transactionState; - internal bool IsCommitted - { - get - { - return (TransactionState.Committed == _transactionState); - } - } + internal bool IsCommitted => TransactionState.Committed == _transactionState; - internal bool IsCompleted - { - get - { - return (TransactionState.Aborted == _transactionState + internal bool IsCompleted => TransactionState.Aborted == _transactionState || TransactionState.Committed == _transactionState - || TransactionState.Unknown == _transactionState); - } - } + || TransactionState.Unknown == _transactionState; - internal bool IsDelegated - { - get - { - bool result = (TransactionType.Delegated == _transactionType); - return result; - } - } + internal bool IsDelegated => TransactionType.Delegated == _transactionType; - internal bool IsDistributed - { - get - { - bool result = (TransactionType.Distributed == _transactionType); - return result; - } - } + internal bool IsDistributed => TransactionType.Distributed == _transactionType; - internal bool IsLocal - { - get - { - bool result = (TransactionType.LocalFromTSQL == _transactionType + internal bool IsLocal => TransactionType.LocalFromTSQL == _transactionType || TransactionType.LocalFromAPI == _transactionType - ); - return result; - } - } +#if NETFRAMEWORK + || TransactionType.Context == _transactionType +#endif + + ; internal bool IsOrphaned { @@ -172,29 +125,11 @@ internal bool IsOrphaned } } - internal bool IsZombied - { - get - { - return (null == _innerConnection); - } - } + internal bool IsZombied => null == _innerConnection; - internal int ObjectID - { - get - { - return _objectID; - } - } + internal int ObjectID => _objectID; - internal int OpenResultsCount - { - get - { - return _openResultCount; - } - } + internal int OpenResultsCount => _openResultCount; internal SqlTransaction Parent { @@ -213,10 +148,7 @@ internal SqlTransaction Parent internal long TransactionId { - get - { - return _transactionId; - } + get => _transactionId; set { Debug.Assert(NullTransactionId == _transactionId, "setting transaction cookie while one is active?"); @@ -224,10 +156,7 @@ internal long TransactionId } } - internal void Activate() - { - _transactionState = TransactionState.Active; - } + internal void Activate() => _transactionState = TransactionState.Active; private void CheckTransactionLevelAndZombie() { @@ -245,6 +174,10 @@ private void CheckTransactionLevelAndZombie() { throw; } +#if NETFRAMEWORK + ADP.TraceExceptionWithoutRethrow(e); +#endif + Zombie(); // If exception caught when trying to check level, zombie. } } @@ -267,6 +200,9 @@ internal void CloseFromConnection() } finally { +#if NETFRAMEWORK + TdsParser.ReliabilitySection.Assert("unreliable call to CloseFromConnection"); // you need to setup for a thread abort somewhere before you call this method +#endif if (processFinallyBlock) { // Always ensure we're zombied; Yukon will send an EnvChange that @@ -295,6 +231,18 @@ internal void Commit() // COMMIT ignores transaction names, and so there is no reason to pass it anything. COMMIT // simply commits the transaction from the most recent BEGIN, nested or otherwise. _innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Commit, null, IsolationLevel.Unspecified, null, false); +#if NETFRAMEWORK + // SQL BU DT 291159 - perform full Zombie on pre-Yukon, but do not actually + // complete internal transaction until informed by server in the case of Yukon + // or later. + if (!IsZombied && !_innerConnection.IsYukonOrNewer) + { + // Since nested transactions are no longer allowed, set flag to false. + // This transaction has been completed. + Zombie(); + } + else +#endif { ZombieParent(); } @@ -330,8 +278,8 @@ internal int DecrementAndObtainOpenResultCount() internal void Dispose() { - this.Dispose(true); - System.GC.SuppressFinalize(this); + Dispose(true); + GC.SuppressFinalize(this); } private void Dispose(bool disposing) @@ -361,9 +309,11 @@ private int GetServerTransactionLevel() SqlParameter parameter = new SqlParameter("@out", SqlDbType.Int); parameter.Direction = ParameterDirection.Output; transactionLevelCommand.Parameters.Add(parameter); - +#if NETFRAMEWORK + transactionLevelCommand.RunExecuteReader(CommandBehavior.Default, RunBehavior.UntilDone, returnStream: false, nameof(GetServerTransactionLevel)); +#else transactionLevelCommand.RunExecuteReader(CommandBehavior.Default, RunBehavior.UntilDone, returnStream: false); - +#endif return (int)parameter.Value; } } @@ -447,6 +397,15 @@ internal void Rollback(string transactionName) try { _innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Rollback, transactionName, IsolationLevel.Unspecified, null, false); +#if NETFRAMEWORK + if (!IsZombied && !_innerConnection.IsYukonOrNewer) + { + // Check if Zombied before making round-trip to server. + // Against Yukon we receive an envchange on the ExecuteTransaction above on the + // parser that calls back into SqlTransaction for the Zombie() call. + CheckTransactionLevelAndZombie(); + } +#endif } catch (Exception e) { @@ -509,7 +468,8 @@ internal void Zombie() // Number 1 needs to be done whenever a SqlTransaction object is completed. Number // 2 is only done when a transaction is actually completed. Since users can begin // transactions both in and outside of the API, and since nested begins are not actual - // transactions we need to distinguish between #1 and #2. + // transactions we need to distinguish between #1 and #2.See SQL BU DT 291159 + // for further details. ZombieParent(); @@ -526,15 +486,19 @@ private void ZombieParent() { if (_parent != null && _parent.TryGetTarget(out SqlTransaction parent)) { - parent.Zombie(); + parent.Zombie(); } _parent = null; } - internal string TraceString() - { - return string.Format(/*IFormatProvider*/ null, "(ObjId={0}, tranId={1}, state={2}, type={3}, open={4}, disp={5}", - ObjectID, _transactionId, _transactionState, _transactionType, _openResultCount, _disposing); - } + internal string TraceString() => string.Format(/*IFormatProvider*/ null, + "(ObjId={0}, tranId={1}, state={2}, type={3}, open={4}, disp={5}", + ObjectID, _transactionId, _transactionState, _transactionType, _openResultCount, _disposing); + +#if NETFRAMEWORK + + internal bool IsContext => TransactionType.Context == _transactionType; + +#endif } -} + } From 1954d7d11778b196e47bef696ab8e391e5f0bdbd Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Wed, 13 Oct 2021 16:01:14 -0700 Subject: [PATCH 2/8] Adding missed file update of netfx --- .../netfx/src/Microsoft.Data.SqlClient.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 1fb9b7e0a3..e16bce078e 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -512,7 +512,9 @@ - + + Microsoft\Data\SqlClient\SqlInternalTransaction.cs + From 9d600dd67e131783eae1ab7f3eba4318a89b20cd Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Wed, 13 Oct 2021 16:08:08 -0700 Subject: [PATCH 3/8] adding missing ; --- .../src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs index 4064149dd4..4e7bae98fc 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs @@ -17,7 +17,7 @@ internal enum TransactionState Aborted = 2, Committed = 3, Unknown = 4, - } + }; internal enum TransactionType { From aed500317d32b1f534761ed4ce64977893262c30 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Mon, 18 Oct 2021 09:15:55 -0700 Subject: [PATCH 4/8] Addressed reviwer's comment --- .../src/Microsoft.Data.SqlClient.csproj | 6 +- .../netfx/src/Microsoft.Data.SqlClient.csproj | 7 +- .../Data/SqlClient/SqlInternalTransaction.cs | 67 +++++++++---------- 3 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index baaaac4578..54ad210918 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -43,6 +43,9 @@ Microsoft\Data\Sql\SqlNotificationRequest.cs + + Microsoft\Data\SqlClient\SqlInternalTransaction.cs + Microsoft\Data\Common\ActivityCorrelator.cs @@ -539,9 +542,6 @@ - - Microsoft\Data\SqlClient\SqlInternalTransaction.cs - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index d170627004..1a57545b99 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -98,6 +98,9 @@ Microsoft\Data\SqlClient\SqlClientLogger.cs + + Microsoft\Data\SqlClient\SqlInternalTransaction.cs + Microsoft\Data\Common\ActivityCorrelator.cs @@ -314,6 +317,7 @@ Microsoft\Data\SqlClient\SqlCommandBuilder.cs + Component Microsoft\Data\SqlClient\SqlCommandSet.cs @@ -519,9 +523,6 @@ - - Microsoft\Data\SqlClient\SqlInternalTransaction.cs - diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs index 4e7bae98fc..d59f75ff96 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs @@ -17,7 +17,7 @@ internal enum TransactionState Aborted = 2, Committed = 3, Unknown = 4, - }; + } internal enum TransactionType { @@ -26,22 +26,22 @@ internal enum TransactionType Delegated = 3, Distributed = 4, Context = 5, // only valid in proc. - }; + } sealed internal class SqlInternalTransaction { internal const long NullTransactionId = 0; private TransactionState _transactionState; - private TransactionType _transactionType; + private readonly TransactionType _transactionType; private long _transactionId; // passed in the MARS headers private int _openResultCount; // passed in the MARS headers private SqlInternalConnection _innerConnection; private bool _disposing; // used to prevent us from throwing exceptions while we're disposing private WeakReference _parent; // weak ref to the outer transaction object; needs to be weak to allow GC to occur. - private static int _objectTypeCount; // EventSource counter - internal readonly int _objectID = Interlocked.Increment(ref _objectTypeCount); + private static int s_objectTypeCount; // EventSource counter + internal readonly int _objectID = Interlocked.Increment(ref s_objectTypeCount); internal bool RestoreBrokenConnection { get; set; } internal bool ConnectionHasBeenRestored { get; set; } @@ -70,29 +70,28 @@ internal SqlInternalTransaction(SqlInternalConnection innerConnection, Transacti // Return true if we are an API started local transaction, or if we were a TSQL // started local transaction and were then wrapped with a parent transaction as // a result of a later API begin transaction. - (TransactionType.LocalFromAPI == _transactionType) || - (TransactionType.LocalFromTSQL == _transactionType && _parent != null); + (_transactionType == TransactionType.LocalFromAPI) || + (_transactionType == TransactionType.LocalFromTSQL && _parent != null); - internal bool IsAborted => TransactionState.Aborted == _transactionState; + internal bool IsAborted => _transactionState == TransactionState.Aborted; - internal bool IsActive => TransactionState.Active == _transactionState; + internal bool IsActive => _transactionState == TransactionState.Active; - internal bool IsCommitted => TransactionState.Committed == _transactionState; + internal bool IsCommitted => _transactionState == TransactionState.Committed; - internal bool IsCompleted => TransactionState.Aborted == _transactionState - || TransactionState.Committed == _transactionState - || TransactionState.Unknown == _transactionState; + internal bool IsCompleted => _transactionState == TransactionState.Aborted + || _transactionState == TransactionState.Committed + || _transactionState == TransactionState.Unknown; - internal bool IsDelegated => TransactionType.Delegated == _transactionType; + internal bool IsDelegated =>_transactionType == TransactionType.Delegated; - internal bool IsDistributed => TransactionType.Distributed == _transactionType; + internal bool IsDistributed => _transactionType == TransactionType.Distributed; - internal bool IsLocal => TransactionType.LocalFromTSQL == _transactionType - || TransactionType.LocalFromAPI == _transactionType + internal bool IsLocal => _transactionType == TransactionType.LocalFromTSQL + || _transactionType == TransactionType.LocalFromAPI #if NETFRAMEWORK - || TransactionType.Context == _transactionType + || _transactionType == TransactionType.Context #endif - ; internal bool IsOrphaned @@ -102,7 +101,7 @@ internal bool IsOrphaned // An internal transaction is orphaned when its parent has been // reclaimed by GC. bool result; - if (null == _parent) + if (_parent == null) { // No parent, so we better be LocalFromTSQL. Should we even return in this case - // since it could be argued this is invalid? @@ -125,7 +124,7 @@ internal bool IsOrphaned } } - internal bool IsZombied => null == _innerConnection; + internal bool IsZombied => _innerConnection == null; internal int ObjectID => _objectID; @@ -137,7 +136,7 @@ internal SqlTransaction Parent { SqlTransaction result = null; // Should we protect against this, since this probably is an invalid state? - Debug.Assert(null != _parent, "Why are we calling Parent with no parent?"); + Debug.Assert(_parent != null, "Why are we calling Parent with no parent?"); if (_parent != null && _parent.TryGetTarget(out SqlTransaction target)) { result = target; @@ -287,7 +286,7 @@ private void Dispose(bool disposing) SqlClientEventSource.Log.TryPoolerTraceEvent("SqlInternalTransaction.Dispose | RES | CPOOL | Object Id {0}, Disposing", ObjectID); if (disposing) { - if (null != _innerConnection) + if (_innerConnection != null) { // implicitly rollback if transaction still valid _disposing = true; @@ -295,13 +294,14 @@ private void Dispose(bool disposing) } } } - + /// + /// This function is needed for those times when it is impossible to determine the server's + /// transaction level, unless the user's arguments were parsed - which is something we don't want + ///to do. An example when it is impossible to determine the level is after a rollback. + /// + /// private int GetServerTransactionLevel() { - // This function is needed for those times when it is impossible to determine the server's - // transaction level, unless the user's arguments were parsed - which is something we don't want - // to do. An example when it is impossible to determine the level is after a rollback. - using (SqlCommand transactionLevelCommand = new SqlCommand("set @out = @@trancount", (SqlConnection)(_innerConnection.Owner))) { transactionLevelCommand.Transaction = Parent; @@ -309,11 +309,8 @@ private int GetServerTransactionLevel() SqlParameter parameter = new SqlParameter("@out", SqlDbType.Int); parameter.Direction = ParameterDirection.Output; transactionLevelCommand.Parameters.Add(parameter); -#if NETFRAMEWORK transactionLevelCommand.RunExecuteReader(CommandBehavior.Default, RunBehavior.UntilDone, returnStream: false, nameof(GetServerTransactionLevel)); -#else - transactionLevelCommand.RunExecuteReader(CommandBehavior.Default, RunBehavior.UntilDone, returnStream: false); -#endif + return (int)parameter.Value; } } @@ -496,9 +493,7 @@ internal string TraceString() => string.Format(/*IFormatProvider*/ null, ObjectID, _transactionId, _transactionState, _transactionType, _openResultCount, _disposing); #if NETFRAMEWORK - - internal bool IsContext => TransactionType.Context == _transactionType; - + internal bool IsContext => _transactionType == TransactionType.Context; #endif } - } +} From 1a31178984ea119b1c433b6429924c29c4efb4d6 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Tue, 19 Oct 2021 08:15:22 -0700 Subject: [PATCH 5/8] Addressing Reviewer's comment removed extra line and componenet subtype --- .../netfx/src/Microsoft.Data.SqlClient.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index a5493e72e0..cad37ca548 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -341,7 +341,6 @@ Microsoft\Data\SqlClient\SqlCommandBuilder.cs - Component Microsoft\Data\SqlClient\SqlCommandSet.cs @@ -706,4 +705,4 @@ - \ No newline at end of file + From 0fc5bdf9d744dde07af0e516b4c58777bdf1273a Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Fri, 21 Jan 2022 16:14:11 -0800 Subject: [PATCH 6/8] review comments --- .../Microsoft/Data/SqlClient/SqlInternalTransaction.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs index e509f41a21..114363f5a6 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalTransaction.cs @@ -87,10 +87,14 @@ internal SqlInternalTransaction(SqlInternalConnection innerConnection, Transacti internal bool IsDistributed => _transactionType == TransactionType.Distributed; +#if NETFRAMEWORK + internal bool IsContext => _transactionType == TransactionType.Context; +#endif + internal bool IsLocal => _transactionType == TransactionType.LocalFromTSQL || _transactionType == TransactionType.LocalFromAPI #if NETFRAMEWORK - || _transactionType == TransactionType.Context + || IsContext #endif ; @@ -492,8 +496,6 @@ internal string TraceString() => string.Format(/*IFormatProvider*/ null, "(ObjId={0}, tranId={1}, state={2}, type={3}, open={4}, disp={5}", ObjectID, _transactionId, _transactionState, _transactionType, _openResultCount, _disposing); -#if NETFRAMEWORK - internal bool IsContext => _transactionType == TransactionType.Context; -#endif + } } From 7aebf45737714e5fa2b1e8e7d3193b78f0d27da3 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Mon, 7 Mar 2022 09:49:11 -0800 Subject: [PATCH 7/8] SNI Update SNI Update --- tools/props/Versions.props | 6 +++--- tools/specs/Microsoft.Data.SqlClient.nuspec | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/props/Versions.props b/tools/props/Versions.props index 44002cbbae..d58b93e218 100644 --- a/tools/props/Versions.props +++ b/tools/props/Versions.props @@ -6,7 +6,7 @@ 5.0.0.0 - 5.0.0-dev + 5.0.0-preview1.22062.1 $(NugetPackageVersion) @@ -20,7 +20,7 @@ - 4.0.0 + 5.0.0-preview1.22062.1 4.3.1 4.3.0 @@ -38,7 +38,7 @@ 5.0.0 - 4.0.0 + 5.0.0-preview1.22062.1 5.0.0 5.0.0 5.0.0 diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec index 750ee2f48a..7f5ed91f43 100644 --- a/tools/specs/Microsoft.Data.SqlClient.nuspec +++ b/tools/specs/Microsoft.Data.SqlClient.nuspec @@ -28,7 +28,7 @@ When using NuGet 3.x this package requires at least version 3.4. sqlclient microsoft.data.sqlclient - + @@ -42,7 +42,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + @@ -60,7 +60,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + @@ -78,7 +78,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + From e7931b534e06d5eae68421c3eb5d7e52ee19d6e0 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Mon, 7 Mar 2022 10:11:45 -0800 Subject: [PATCH 8/8] Revert "SNI Update" This reverts commit 7aebf45737714e5fa2b1e8e7d3193b78f0d27da3. --- tools/props/Versions.props | 6 +++--- tools/specs/Microsoft.Data.SqlClient.nuspec | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/props/Versions.props b/tools/props/Versions.props index d58b93e218..44002cbbae 100644 --- a/tools/props/Versions.props +++ b/tools/props/Versions.props @@ -6,7 +6,7 @@ 5.0.0.0 - 5.0.0-preview1.22062.1 + 5.0.0-dev $(NugetPackageVersion) @@ -20,7 +20,7 @@ - 5.0.0-preview1.22062.1 + 4.0.0 4.3.1 4.3.0 @@ -38,7 +38,7 @@ 5.0.0 - 5.0.0-preview1.22062.1 + 4.0.0 5.0.0 5.0.0 5.0.0 diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec index 7f5ed91f43..750ee2f48a 100644 --- a/tools/specs/Microsoft.Data.SqlClient.nuspec +++ b/tools/specs/Microsoft.Data.SqlClient.nuspec @@ -28,7 +28,7 @@ When using NuGet 3.x this package requires at least version 3.4. sqlclient microsoft.data.sqlclient - + @@ -42,7 +42,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + @@ -60,7 +60,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + @@ -78,7 +78,7 @@ When using NuGet 3.x this package requires at least version 3.4. - +