-
Notifications
You must be signed in to change notification settings - Fork 316
Flatten | SqlInternalConnectionTds and SqlInternalConnection #3773
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
benrr101
wants to merge
35
commits into
main
Choose a base branch
from
dev/russellben/flatten/sqlinternalconnection
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 32 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
66c2cd6
Change all possible references from SqlInternalConnection to SqlInter…
benrr101 2d664a6
Move BeginTransaction and BeginSqlTransaction into SqlInternalConnect…
benrr101 c796212
Move ChangeDatabase into SqlInternalConnectionTds, move ChangeDatabas…
benrr101 13c373c
Move EnlistTransaction to SqlInternalConnectionTds
benrr101 a176e2f
Remove abstract ValidateConnectionForExecute
benrr101 c5863e3
Move Enlist into SqlInternalConnectionTds
benrr101 8002ec7
Move EnlistNonNull into SqlInternalConnectionTds
benrr101 202beb5
Move EnlistNull into SqlInternalConnectionTds
benrr101 bb3d541
Removed no longer necessary abstractions in SqlInternalConnection
benrr101 4d39842
Move OnError into SqlInternalConnectionTds
benrr101 58c358f
Move Deactivate into SqlInternalConnectionTds, merge InternalDeactiva…
benrr101 07750f8
Move GetTransactionCookie into SqlInternalConnectionTds
benrr101 dbe9d9e
Move FindLiveReader into SqlInternalConnectionTds
benrr101 355f2d2
Merge SqlInternalConnection.Dispose into SqlInternalConnectionTds
benrr101 74b0c92
Move CleanupTransactionOnCompletion, CreateReferenceCollection into S…
benrr101 ce46515
Introduce a CachedContexts class, move the cached call contexts from …
benrr101 79cf052
Migrate usages of CachedCommandExecuteNonQueryAsyncContext to the new…
benrr101 0a45c97
Migrate usages of CachedCommandExecuteXmlReaderAsyncContext to the ne…
benrr101 7b5a637
Migrate usage of ReadAsyncCallContext to the new class
benrr101 ba4c7df
Migrate usage of IsDBNullAsyncCallContext to the new class.
benrr101 a0a1f24
Comments on CachedContexts
benrr101 41b7f2a
Sure why not move the reader snapshot into the CachedContexts class? …
benrr101 1b52999
Move _whereAbouts and s_globalTransactionTMID
benrr101 8fb7b0e
Merge constructors
benrr101 0e78a6e
Merge AvailableInternalTransaction, CurrentTransaction, HasLocalTrans…
benrr101 858d98e
Merge Connection, ConnectionOptions, CurrentDatabase, CurrentDataSour…
benrr101 6dfbd5d
Remove SqlInternalConnection
benrr101 a83bd7c
Move SqlInternalConnectionTds.cs to SqlConnectionInternal.cs
benrr101 c4db055
Renane Microsoft.Data.SqlClient.SqlInternalConnectionTds to Microsoft…
benrr101 d010d48
Fix one reference to SqlInternalConnectionTds in unit tests
benrr101 4d02cc2
As per copilot comment, rewriting a block in SqlConnectionFactory to …
benrr101 04e5cdf
As per copilot comment, adding more comments to CachedContexts class
benrr101 64766f4
Addressing some feedback from @mdiagle
benrr101 89b92b9
Merge branch 'main' into dev/russellben/flatten/sqlinternalconnection
benrr101 3b795ae
Rename Clear*Context to Take*Context
benrr101 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
180 changes: 180 additions & 0 deletions
180
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/CachedContexts.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| // 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.Threading; | ||
|
|
||
| #nullable enable | ||
|
|
||
| namespace Microsoft.Data.SqlClient.Connection | ||
| { | ||
| /// <summary> | ||
| /// Provides thread-safe caching and sharing of asynchronous call contexts between objects | ||
| /// within a single SQL connection context. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// This internal class manages reusable context objects for various asynchronous operations | ||
| /// such as ExecuteNonQueryAsync, ExecuteReaderAsync, etc, performed on a connection, enabling | ||
| /// efficient reuse and reducing allocations. | ||
| /// | ||
| /// Thread safety is ensured via interlocked operations, allowing concurrent access and | ||
| /// updates without explicit locking. All accessors and mutators are designed to be safe for | ||
| /// use by multiple threads. | ||
| /// | ||
| /// Intended for internal use by connection management infrastructure. | ||
| /// </remarks> | ||
| internal class CachedContexts | ||
| { | ||
| #region Fields | ||
|
|
||
| /// <summary> | ||
| /// Stores reusable context for ExecuteNonQueryAsync invocations. | ||
| /// </summary> | ||
| private SqlCommand.ExecuteNonQueryAsyncCallContext? _commandExecuteNonQueryAsyncContext; | ||
|
|
||
| /// <summary> | ||
| /// Stores reusable context for ExecuteReaderAsync invocations. | ||
| /// </summary> | ||
| private SqlCommand.ExecuteReaderAsyncCallContext? _commandExecuteReaderAsyncContext; | ||
|
|
||
| /// <summary> | ||
| /// Stores reusable context for ExecuteXmlReaderAsync invocations. | ||
| /// </summary> | ||
| private SqlCommand.ExecuteXmlReaderAsyncCallContext? _commandExecuteXmlReaderAsyncContext; | ||
|
|
||
| /// <summary> | ||
| /// Stores reusable context for IsDBNullAsync invocations. | ||
| /// </summary> | ||
| private SqlDataReader.IsDBNullAsyncCallContext? _dataReaderIsDbNullContext; | ||
|
|
||
| /// <summary> | ||
| /// Stores reusable context for ReadAsync invocations. | ||
| /// </summary> | ||
| private SqlDataReader.ReadAsyncCallContext? _dataReaderReadAsyncContext; | ||
|
|
||
| /// <summary> | ||
| /// Stores a data reader snapshot. | ||
| /// </summary> | ||
| private SqlDataReader.Snapshot? _dataReaderSnapshot; | ||
|
|
||
| #endregion | ||
|
|
||
| #region Access Methods | ||
|
|
||
| /// <summary> | ||
| /// Removes and returns the cached ExecuteNonQueryAsync context. | ||
| /// </summary> | ||
| /// <returns>The previously cached context or null when empty.</returns> | ||
| internal SqlCommand.ExecuteNonQueryAsyncCallContext? ClearCommandExecuteNonQueryAsyncContext() => | ||
| Interlocked.Exchange(ref _commandExecuteNonQueryAsyncContext, null); | ||
|
|
||
| /// <summary> | ||
| /// Removes and returns the cached ExecuteReaderAsync context. | ||
| /// </summary> | ||
| /// <returns>The previously cached context or null when empty.</returns> | ||
| internal SqlCommand.ExecuteReaderAsyncCallContext? ClearCommandExecuteReaderAsyncContext() => | ||
| Interlocked.Exchange(ref _commandExecuteReaderAsyncContext, null); | ||
|
|
||
| /// <summary> | ||
| /// Removes and returns the cached ExecuteXmlReaderAsync context. | ||
| /// </summary> | ||
| /// <returns>The previously cached context or null when empty.</returns> | ||
| internal SqlCommand.ExecuteXmlReaderAsyncCallContext? ClearCommandExecuteXmlReaderAsyncContext() => | ||
| Interlocked.Exchange(ref _commandExecuteXmlReaderAsyncContext, null); | ||
|
|
||
| /// <summary> | ||
| /// Removes and returns the cached ReadAsync context. | ||
| /// </summary> | ||
| /// <returns>The previously cached context or null when empty.</returns> | ||
| internal SqlDataReader.ReadAsyncCallContext? ClearDataReaderReadAsyncContext() => | ||
| Interlocked.Exchange(ref _dataReaderReadAsyncContext, null); | ||
|
|
||
| /// <summary> | ||
| /// Removes and returns the cached IsDBNullAsync context. | ||
| /// </summary> | ||
| /// <returns>The previously cached context or null when empty.</returns> | ||
| internal SqlDataReader.IsDBNullAsyncCallContext? ClearDataReaderIsDbNullContext() => | ||
| Interlocked.Exchange(ref _dataReaderIsDbNullContext, null); | ||
|
|
||
| /// <summary> | ||
| /// Removes and returns the cached data reader snapshot. | ||
| /// </summary> | ||
| /// <returns>The previously cached snapshot or null when empty.</returns> | ||
| internal SqlDataReader.Snapshot? ClearDataReaderSnapshot() => | ||
| Interlocked.Exchange(ref _dataReaderSnapshot, null); | ||
|
|
||
| /// <summary> | ||
| /// Attempts to cache the provided ExecuteNonQueryAsync context. | ||
| /// </summary> | ||
| /// <param name="value">Context instance to store.</param> | ||
| /// <returns> | ||
| /// True when the context is cached; false if an existing value is preserved. | ||
| /// </returns> | ||
| internal bool TrySetCommandExecuteNonQueryAsyncContext(SqlCommand.ExecuteNonQueryAsyncCallContext value) => | ||
| TrySetContext(value, ref _commandExecuteNonQueryAsyncContext); | ||
|
|
||
| /// <summary> | ||
| /// Attempts to cache the provided ExecuteReaderAsync context. | ||
| /// </summary> | ||
| /// <param name="value">Context instance to store.</param> | ||
| /// <returns> | ||
| /// True when the context is cached; false if an existing value is preserved. | ||
| /// </returns> | ||
| internal bool TrySetCommandExecuteReaderAsyncContext(SqlCommand.ExecuteReaderAsyncCallContext value) => | ||
| TrySetContext(value, ref _commandExecuteReaderAsyncContext); | ||
|
|
||
| /// <summary> | ||
| /// Attempts to cache the provided ExecuteXmlReaderAsync context. | ||
| /// </summary> | ||
| /// <param name="value">Context instance to store.</param> | ||
| /// <returns> | ||
| /// True when the context is cached; false if an existing value is preserved. | ||
| /// </returns> | ||
| internal bool TrySetCommandExecuteXmlReaderAsyncContext(SqlCommand.ExecuteXmlReaderAsyncCallContext value) => | ||
| TrySetContext(value, ref _commandExecuteXmlReaderAsyncContext); | ||
|
|
||
| /// <summary> | ||
| /// Attempts to cache the provided ReadAsync context. | ||
| /// </summary> | ||
| /// <param name="value">Context instance to store.</param> | ||
| /// <returns> | ||
| /// True when the context is cached; false if an existing value is preserved. | ||
| /// </returns> | ||
| internal bool TrySetDataReaderReadAsyncContext(SqlDataReader.ReadAsyncCallContext value) => | ||
| TrySetContext(value, ref _dataReaderReadAsyncContext); | ||
|
|
||
| /// <summary> | ||
| /// Attempts to cache the provided IsDBNullAsync context. | ||
| /// </summary> | ||
| /// <param name="value">Context instance to store.</param> | ||
| /// <returns> | ||
| /// True when the context is cached; false if an existing value is preserved. | ||
| /// </returns> | ||
| internal bool TrySetDataReaderIsDbNullContext(SqlDataReader.IsDBNullAsyncCallContext value) => | ||
| TrySetContext(value, ref _dataReaderIsDbNullContext); | ||
|
|
||
| /// <summary> | ||
| /// Attempts to cache the provided data reader snapshot context. | ||
| /// </summary> | ||
| /// <param name="value">Context instance to store.</param> | ||
| /// <returns> | ||
| /// True when the snapshot is cached; false if an existing snapshot is preserved. | ||
| /// </returns> | ||
| internal bool TrySetDataReaderSnapshot(SqlDataReader.Snapshot value) => | ||
| TrySetContext(value, ref _dataReaderSnapshot); | ||
|
|
||
| #endregion | ||
|
|
||
| private static bool TrySetContext<TContext>(TContext value, ref TContext? location) | ||
| where TContext : class | ||
| { | ||
| if (value is null) | ||
| { | ||
| throw new ArgumentNullException(nameof(value)); | ||
| } | ||
|
|
||
| return Interlocked.CompareExchange(ref location, value, null) is null; | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
TrySetContextmethod throwsArgumentNullExceptionwhenvalueis null. However, the public-facing methods that call this helper (e.g.,TrySetCommandExecuteNonQueryAsyncContext,TrySetDataReaderSnapshot) don't document this behavior. Consider adding XML documentation to these methods indicating that they will throwArgumentNullExceptionif a null value is provided, or handle the null case gracefully by returning false instead of throwing.