Skip to content

Update SQL Server VECTOR_SEARCH() support with WithApproximate LINQ operator#38144

Merged
roji merged 4 commits intomainfrom
roji/vector-search-updates
Apr 24, 2026
Merged

Update SQL Server VECTOR_SEARCH() support with WithApproximate LINQ operator#38144
roji merged 4 commits intomainfrom
roji/vector-search-updates

Conversation

@roji
Copy link
Copy Markdown
Member

@roji roji commented Apr 20, 2026

Updates the EF Core SQL Server provider's vector search support to align with the latest Azure SQL VECTOR_SEARCH() syntax and semantics.

Changes

API changes

  • Removed topN parameter from EF.Functions.VectorSearch() (deprecated by SQL Server).
  • Added WithApproximate<T>() LINQ operator — opt-in modifier that adds WITH APPROXIMATE to the SQL TOP clause, instructing SQL Server to use the vector index for ANN search. Without it, an exact kNN search is performed.

Design

  • WithApproximate() is placed after Take() in the LINQ pipeline, mirroring the T-SQL SELECT TOP(N) WITH APPROXIMATE syntax.
  • Internally, WithApproximateExpression wraps the Limit in the SelectExpression. It flows transparently through PushdownIntoSubquery(), preserving WITH APPROXIMATE in inner subqueries (e.g. reranking patterns).
  • No implicit ORDER BY is added — users add explicit OrderBy as needed, matching T-SQL behavior.
  • Throws InvalidOperationException if WithApproximate() is used without a preceding Take().

Rendering

  • WithApproximateExpression is identified and rendered in VisitExtension in SqlServerQuerySqlGenerator, keeping GenerateTop generic.
  • The nullability processor treats WithApproximateExpression as a pure pass-through.

Tests (12 tests, all passing against Azure SQL)

  • VectorDistance_with_parameter / VectorDistance_with_constant
  • VectorSearch_project_entity_and_distance (approximate)
  • VectorSearch_exact_knn (no WithApproximate)
  • VectorSearch_project_entity_only_with_distance_filter
  • VectorSearch_in_subquery
  • VectorSearch_with_Where_before_Take / VectorSearch_with_Join_before_Take
  • VectorSearch_with_Take_and_Skip (pushdown preserves WITH APPROXIMATE)
  • VectorSearch_reranking (approximate inner + exact outer re-rank)
  • WithApproximate_without_Take_throws
  • Length (VECTORPROPERTY)

NativeAOT compatible

Uses new Func<IQueryable<T>, IQueryable<T>>(WithApproximate).Method pattern instead of MakeGenericMethod.

All APIs remain [Experimental("EF9105")].

Closes #36384

@roji roji requested a review from a team as a code owner April 20, 2026 09:39
Copilot AI review requested due to automatic review settings April 20, 2026 09:39
- Remove deprecated topN parameter from VectorSearch API
- Add WithApproximate() LINQ operator for opt-in approximate search
- Implicit ORDER BY Distance for VectorSearch results
- Update SQL generation: GenerateTop checks WithApproximateExpression
- Handle nullability processing for WithApproximateExpression
- Remove SetOffset from SelectExpression (no longer needed)
- Add comprehensive tests including exact kNN, approximate, subquery,
  joins, skip/take patterns
- Refresh API baselines

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@roji roji force-pushed the roji/vector-search-updates branch from 81bc04c to 06e7ec7 Compare April 20, 2026 09:41
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates EF Core’s SQL Server provider vector search support to match the latest Azure SQL VECTOR_SEARCH() behavior by separating “exact kNN” vs “approximate ANN” via an explicit LINQ opt-in.

Changes:

  • Removes the topN parameter from SqlServerQueryableExtensions.VectorSearch() and relies on Take() instead.
  • Adds WithApproximate<T>() to render SELECT TOP(N) WITH APPROXIMATE ... for ANN/vector-index usage.
  • Wires WithApproximateExpression through SQL generation and nullability processing; expands/updates SQL Server functional tests and string resources.

Reviewed changes

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

Show a summary per file
File Description
test/EFCore.SqlServer.FunctionalTests/Query/Translations/VectorTranslationsSqlServerTest.cs Updates/extends Azure SQL-only tests to cover exact vs approximate vector search SQL.
src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs Treats WithApproximateExpression as pass-through during nullability processing.
src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs Translates WithApproximate() by wrapping SelectExpression.Limit, and validates call shape.
src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs Renders TOP(N) WITH APPROXIMATE by recognizing WithApproximateExpression during SQL generation.
src/EFCore.SqlServer/Query/Internal/SqlExpressions/WithApproximateExpression.cs New internal SQL expression node used to carry the WITH APPROXIMATE modifier.
src/EFCore.SqlServer/Properties/SqlServerStrings.resx Adds new user-facing resource strings for WithApproximate() validation errors.
src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs Adds generated accessors for the new resource strings.
src/EFCore.SqlServer/Extensions/SqlServerQueryableExtensions.cs Updates VectorSearch signature and introduces the WithApproximate() LINQ operator.
src/EFCore.SqlServer/EFCore.SqlServer.baseline.json Updates API baseline to reflect the signature change and the new experimental API.
Files not reviewed (1)
  • src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs: Language not supported
Comments suppressed due to low confidence (1)

src/EFCore.SqlServer/Properties/SqlServerStrings.resx:425

  • The guidance in this message is misleading: rewriting Skip(...).Take(...).WithApproximate() to Take(...).WithApproximate().Skip(...) is not semantically equivalent (it changes the number of returned rows unless the Take is adjusted to account for the skipped rows). Consider rewording to avoid suggesting an incorrect rewrite, or explicitly describe the correct equivalent rewrite (e.g., taking enough rows to cover the skip) depending on what you intend to support.
  <data name="VectorPropertiesNotSupportedInJson" xml:space="preserve">
    <value>Vector property '{propertyName}' is on '{structuralType}' which is mapped to JSON. Vector properties are not supported within JSON documents.</value>
  </data>

Comment thread src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs Outdated
- Remove unused using directive in SqlServerSqlNullabilityProcessor
- Add test for Skip().Take().WithApproximate() throwing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 22, 2026 14:50
@roji roji removed the needs-design label Apr 22, 2026
Copy link
Copy Markdown

Copilot AI left a comment

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 15 out of 16 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs: Language not supported

@roji roji force-pushed the roji/vector-search-updates branch from acebe85 to d82024e Compare April 22, 2026 18:27
Copilot AI review requested due to automatic review settings April 22, 2026 18:52
Copy link
Copy Markdown

Copilot AI left a comment

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 18 out of 19 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs: Language not supported

@roji
Copy link
Copy Markdown
Member Author

roji commented Apr 22, 2026

@AndriySvyryd this should be ready for reviewing - I've added the warning for when EF.Functions.VectorSearch() is used without WithApproximate() on a column with an index, as discussed.

@roji roji merged commit 29d5f60 into main Apr 24, 2026
27 checks passed
@roji roji deleted the roji/vector-search-updates branch April 24, 2026 14:18
@github-actions github-actions Bot added the api-review This PR or issue is introducing public API changes that need to be reviewed label Apr 24, 2026
@github-actions
Copy link
Copy Markdown
Contributor

API review baseline changes for src/EFCore.SqlServer/EFCore.SqlServer.baseline.json

Show diff

The diff below was generated by ApiChief between the base and the PR.

  static class Microsoft.EntityFrameworkCore.Diagnostics.SqlServerEventId
+ static readonly Microsoft.Extensions.Logging.EventId VectorSearchWithoutApproximateWarning
  static class Microsoft.EntityFrameworkCore.SqlServerQueryableExtensions
+ static IQueryable<T> WithApproximate<T>(this IQueryable<T> source);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-review This PR or issue is introducing public API changes that need to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SQL Server: Implement support for VECTOR_SEARCH()

3 participants