Skip to content

Introduce Async API counterparts for AE base class#3673

Open
cheenamalhotra wants to merge 13 commits into
mainfrom
dev/cheena/async-ae
Open

Introduce Async API counterparts for AE base class#3673
cheenamalhotra wants to merge 13 commits into
mainfrom
dev/cheena/async-ae

Conversation

@cheenamalhotra

@cheenamalhotra cheenamalhotra commented Oct 8, 2025

Copy link
Copy Markdown
Member

Summary

Introduces async API counterparts for the SqlColumnEncryptionKeyStoreProvider abstract base class (Always Encrypted). This enables custom key store providers to implement truly asynchronous key operations instead of being forced to block on synchronous calls during query execution.

Fixes #3672

Public API

Four new virtual methods added to SqlColumnEncryptionKeyStoreProvider:

public virtual Task<byte[]> DecryptColumnEncryptionKeyAsync(
    string masterKeyPath, string encryptionAlgorithm,
    byte[] encryptedColumnEncryptionKey,
    CancellationToken cancellationToken = default);

public virtual Task<byte[]> EncryptColumnEncryptionKeyAsync(
    string masterKeyPath, string encryptionAlgorithm,
    byte[] columnEncryptionKey,
    CancellationToken cancellationToken = default);

public virtual Task<byte[]> SignColumnMasterKeyMetadataAsync(
    string masterKeyPath, bool allowEnclaveComputations,
    CancellationToken cancellationToken = default);

public virtual Task<bool> VerifyColumnMasterKeyMetadataAsync(
    string masterKeyPath, bool allowEnclaveComputations,
    byte[] signature,
    CancellationToken cancellationToken = default);

Design Decisions

  • Single overload with CancellationToken = default — no separate convenience overloads
  • Default implementation wraps sync counterpart via Task.FromResult / Task.FromException so existing providers work without changes
  • Fatal exceptions are not caught — uses ADP.IsCatchableExceptionType(e) filter in catch blocks (consistent with runtime patterns for StackOverflowException, OutOfMemoryException, etc.)

Changes

File Description
src/.../SqlColumnEncryptionKeyStoreProvider.cs Implementation of 4 virtual async methods
src/.../ref/Microsoft.Data.SqlClient.cs Reference assembly surface
doc/snippets/.../SqlColumnEncryptionKeyStoreProvider.xml XML documentation
specs/002-async-always-encrypted/spec.md Design specification
tests/.../SqlColumnEncryptionKeyStoreProviderAsyncShould.cs 16 unit tests

Testing

  • 16 unit tests covering: default sync fallback, faulted task propagation, cancellation support, default parameter behavior
  • Builds clean on all target frameworks (net462, net8.0, net9.0)
  • No breaking changes — existing providers continue to work without modification

Checklist

  • Tests added
  • Public API changes documented (ref assembly + XML docs)
  • Design spec included
  • No breaking changes introduced

@cheenamalhotra cheenamalhotra added this to the 7.0-preview2 milestone Oct 8, 2025
@cheenamalhotra cheenamalhotra requested a review from a team as a code owner October 8, 2025 04:20
Copilot AI review requested due to automatic review settings October 8, 2025 04:20
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Oct 8, 2025

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

Adds asynchronous counterparts to key store provider APIs in SqlColumnEncryptionKeyStoreProvider to enable async implementations for Always Encrypted key operations.
Key changes:

  • Introduced async virtual methods (Decrypt/Encrypt column encryption key, Sign/Verify CMK metadata) that currently throw NotImplementedException.
  • Added corresponding XML documentation entries for the new async methods.
  • Minor wording adjustments in existing XML return documentation.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.

File Description
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionKeyStoreProvider.cs Adds async virtual method stubs for encryption key and metadata operations.
doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionKeyStoreProvider.xml Documents newly added async methods and adjusts some existing return descriptions.

Comment thread doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionKeyStoreProvider.xml Outdated
Comment thread doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionKeyStoreProvider.xml Outdated
@paulmedynski paulmedynski self-assigned this Oct 8, 2025

@paulmedynski paulmedynski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Asking for clarification on return types and synchronous implementation.

@benrr101 benrr101 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For new APIs we should have some discussion on the signatures. Definitely won't be able to get this in before preview2.

@benrr101 benrr101 modified the milestones: 7.0-preview2, 7.0.0 Oct 8, 2025
@cheenamalhotra cheenamalhotra moved this from To triage to In progress in SqlClient Board Oct 8, 2025
@cheenamalhotra cheenamalhotra moved this from In progress to In review in SqlClient Board Oct 8, 2025
@cheenamalhotra cheenamalhotra modified the milestones: 7.0.0, 7.0.0-preview3 Oct 9, 2025
paulmedynski
paulmedynski previously approved these changes Oct 10, 2025
@github-actions

Copy link
Copy Markdown

This pull request has been marked as stale due to inactivity for more than 30 days.

If you would like to keep this pull request open, please provide an update or respond to any comments. Otherwise, it will be closed automatically in 7 days.

@github-actions github-actions Bot added the Stale The Issue or PR has become stale and will be automatically closed shortly if no activity occurs. label Nov 10, 2025
@cheenamalhotra

Copy link
Copy Markdown
Member Author

Wait, wait 🙈

@github-actions github-actions Bot removed the Stale The Issue or PR has become stale and will be automatically closed shortly if no activity occurs. label Nov 11, 2025
@mdaigle mdaigle modified the milestones: 7.0.0-preview3, 7.0.0-preview4 Dec 2, 2025
@github-actions

github-actions Bot commented Jan 2, 2026

Copy link
Copy Markdown

This pull request has been marked as stale due to inactivity for more than 30 days.

If you would like to keep this pull request open, please provide an update or respond to any comments. Otherwise, it will be closed automatically in 7 days.

@github-actions github-actions Bot added the Stale The Issue or PR has become stale and will be automatically closed shortly if no activity occurs. label Jan 2, 2026
@cheenamalhotra

Copy link
Copy Markdown
Member Author

Stay

@github-actions github-actions Bot removed the Stale The Issue or PR has become stale and will be automatically closed shortly if no activity occurs. label Jan 3, 2026
@cheenamalhotra cheenamalhotra added the Public API 🆕 Issues/PRs that introduce new APIs to the driver. label Jan 13, 2026
@cheenamalhotra cheenamalhotra removed this from the 7.0.0-preview4 milestone Jan 20, 2026
- Reorder XML doc elements to place <summary> before <param> tags
- Improve masterKeyPath descriptions (provider-specific format examples)
- Improve encryptionAlgorithm descriptions (include RSA_OAEP example)
- Fix columnEncryptionKey param: 'The column encryption key to encrypt'
- Remove 'digitally' and redundant sentence from Sign summary
- Wrap long lines to ~100 chars throughout
- Use <see cref> for NotImplementedException in Verify docs
- Add #nullable enable/restore around new async APIs in ref assembly

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 20:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
- Split async methods into two overloads per .NET standard library pattern:
  virtual overload with explicit CancellationToken (overridable), and
  non-virtual convenience overload without it (passes CancellationToken.None)
- Default implementation checks CancellationToken.IsCancellationRequested
  and returns Task.FromCanceled before invoking sync method
- Move tests from FunctionalTests to UnitTests
- Add 4 cancellation token tests validating cancelled task behavior
- Update <returns> tags to use <see cref="T:System.Byte[]" />
- Update spec to reflect two-overload design decision

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 21:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
- Fix test namespace to Microsoft.Data.SqlClient.UnitTests.AlwaysEncrypted
  (matching existing convention in UnitTests project)
- Improve allowEnclaveComputations param docs: explain that when true, the
  signature covers the enclave-enabled property for later verification
- Improve signature param docs: clarify it's the byte array from
  SignColumnMasterKeyMetadata with provider-specific format
- Add 'live token' tests validating non-cancelled token doesn't interfere
  with default implementation completion

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 10, 2026 01:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
Comment thread src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Outdated
The ref project inherits nullable context from Directory.Build.props,
so adding #nullable enable/restore blocks caused 'throw null;' to emit
CS8597 errors. Remove the directives to match the ref file convention.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 10, 2026 01:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

- Replace SemaphoreSlim pattern with MemoryCache.GetOrCreateAsync for
  IMemoryCache-backed caches (AKV provider)
- Keep check-release-fetch-relock only for custom-cache sites
- Remove superseded Decision 8, consolidate to 7 concise decisions
- Convert requirements and entities to compact tables
- Reduce from 448 to 298 lines

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 10, 2026 01:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

…d tests

- Add XML <summary> documentation to every [Fact] method and test helpers
- Add using Microsoft.Data.SqlClient for explicit namespace import
- Add SignColumnMasterKeyMetadataAsync_NoCancellationOverload_ReturnsFaultedTask
- Add VerifyColumnMasterKeyMetadataAsync_NoCancellationOverload_ReturnsFaultedTask
- Organize tests into regions: fallback, faulted, cancellation, convenience

Total: 16 tests passing

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Remove non-virtual convenience overloads. Each async method is now a
single virtual method with 'CancellationToken cancellationToken = default'
so callers can omit the token and derived classes override one method.

- Remove 4 non-virtual NoCancellation overloads from implementation
- Remove 4 NoCancellation entries from ref assembly
- Remove 4 NoCancellation XML doc blocks
- Update spec Decision 2 and FR-002 for single-overload pattern
- Rename test region from 'Convenience overloads' to 'Default parameter'

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Fatal exceptions (OOM, StackOverflow, ThreadAbort, etc.) must not be
wrapped in Task.FromException — they should propagate synchronously.
Use the existing ADP.IsCatchableExceptionType guard in exception
filters, matching the pattern used in SqlDataReader and throughout
the repo.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread specs/002-async-always-encrypted/spec.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Public API 🆕 Issues/PRs that introduce new APIs to the driver.

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

Feature | Async friendly Always Encrypted support

8 participants