Skip to content

.Net: fix: Remove OldFilter dependency from VectorStoreTextSearch (#1…#13564

Merged
markwallace-microsoft merged 1 commit intomicrosoft:feature-text-search-linqfrom
alzarei:remove-oldfilter-dependency
Feb 19, 2026
Merged

.Net: fix: Remove OldFilter dependency from VectorStoreTextSearch (#1…#13564
markwallace-microsoft merged 1 commit intomicrosoft:feature-text-search-linqfrom
alzarei:remove-oldfilter-dependency

Conversation

@alzarei
Copy link
Contributor

@alzarei alzarei commented Feb 19, 2026

.Net: fix: Remove OldFilter dependency from VectorStoreTextSearch (#10456)

Addresses @roji's feedback on PR #13384: Remove the dependency on MEVD's obsolete OldFilter property from VectorStoreTextSearch, enabling MEVD to drop OldFilter before publishing 1.0 provider versions.

Context
This is a follow-up change on the feature-text-search-linq branch addressing @roji's review comment. The change converts the legacy ITextSearch code path from using VectorSearchFilter.OldFilter to building a LINQ expression tree via BuildFilterExpression(), so both legacy and modern paths now converge on VectorSearchOptions<TRecord>.Filter.

Motivation and Context

Why is this change required?

@roji identified that VectorStoreTextSearch's legacy path hands FilterClause values directly to MEVD via OldFilter, which means MEVD cannot remove OldFilter while that dependency exists. His priority is to remove OldFilter from MEVD before publishing 1.0 versions of most providers — an [Obsolete] property on a 1.0 API is undesirable.

What problem does it solve?

  • Removes the last SK-level dependency on MEVD's obsolete OldFilter property
  • Enables MEVD to drop OldFilter independently, unblocking 1.0 provider releases
  • Eliminates #pragma warning disable CS0618 suppressions for OldFilter/VectorSearchFilter usage
  • Corrects the ADR-0065 Option 2 rejection rationale (building expression trees ≠ compiling them)

What scenario does it contribute to?

Unblocks MEVD 1.0 provider releases by removing the coupling between SK's legacy text search path and MEVD's obsolete filtering API.

Issue Link: #10456

Description

Code Change: VectorStoreTextSearch.cs

Replaced the legacy path's OldFilter assignment with a new BuildFilterExpression() method that converts FilterClause values to a LINQ expression tree:

Before:

#pragma warning disable CS0618 // VectorSearchFilter is obsolete
OldFilter = searchOptions.Filter?.FilterClauses is not null
    ? new VectorSearchFilter(searchOptions.Filter.FilterClauses)
    : null,
#pragma warning restore CS0618

After:

Filter = searchOptions.Filter?.FilterClauses is not null
    ? BuildFilterExpression(searchOptions.Filter.FilterClauses)
    : null,

BuildFilterExpression() details:

  • Iterates FilterClause instances, currently handling EqualToFilterClause (the only type TextSearchFilter produces)
  • For each clause: resolves PropertyInfo via typeof(TRecord).GetProperty() (trim-safe because TRecord has [DynamicallyAccessedMembers(PublicProperties)]), builds Expression.PropertyExpression.EqualExpression.AndAlso
  • Uses PropertyInfo overload of Expression.Property() to avoid IL2026 trimming warning (the string overload has [RequiresUnreferencedCode])
  • Returns Expression<Func<TRecord, bool>> or null if no clauses
  • Throws NotSupportedException for unsupported clause types, InvalidOperationException for missing properties

AOT compatibility: Building expression trees (Expression.Property, Expression.Equal, Expression.Lambda) is pure data-structure construction — fully AOT-compatible. MEVD's VectorSearchOptions<TRecord>.Filter analyzes the tree without calling Expression.Compile().

ADR Update: 0065-linq-based-text-search-filtering.md

  • Architecture diagram: Updated Pattern A to show BuildFilterExpression() converting clauses to LINQ trees, both paths converging on VectorSearchOptions.Filter
  • Pattern A description: Updated to reflect both paths now use VectorSearchOptions.Filter
  • Option 2 rationale: Corrected the rejection — original assessment incorrectly claimed RequiresDynamicCode would cascade; in fact, only Expression.Compile() requires dynamic code, not tree construction. Added update note explaining the distinction.

Contribution Checklist

Validation

Check Result
Format (dotnet format --verify-no-changes) ✅ Pass
Build (dotnet build --configuration Release --warnaserror) ✅ Pass (0 warnings, 0 errors)
Unit tests (SemanticKernel.UnitTests) ✅ Pass (1606/1606)
AOT publish (dotnet publish --configuration Release, net9.0) ✅ Pass (0 warnings)
AOT publish (dotnet publish --configuration Release, net10.0) ✅ Pass (0 warnings)

@alzarei alzarei requested a review from a team as a code owner February 19, 2026 06:13
@moonbox3 moonbox3 added .NET Issue or Pull requests regarding .NET code documentation labels Feb 19, 2026
@alzarei alzarei changed the title .Net: fix: Remove OldFilter dependency from VectorStoreTextSearch (#1… .Net: fix: Remove OldFilter dependency from VectorStoreTextSearch Feb 19, 2026
@github-actions github-actions bot changed the title .Net: fix: Remove OldFilter dependency from VectorStoreTextSearch .Net: fix: Remove OldFilter dependency from VectorStoreTextSearch (#1… Feb 19, 2026
@alzarei alzarei mentioned this pull request Feb 19, 2026
4 tasks
…crosoft#10456)

Address @roji's feedback on PR microsoft#13384: convert legacy ITextSearch path from
using VectorSearchFilter.OldFilter to building LINQ expression trees via
BuildFilterExpression(), enabling MEVD to drop OldFilter before 1.0 releases.

- Replace OldFilter with BuildFilterExpression() in legacy ExecuteVectorSearchAsync
- Use PropertyInfo overload of Expression.Property() to avoid IL2026 trimming warning
- Update ADR-0065: correct Option 2 rejection rationale (tree building != compiling)
- Update ADR-0065: architecture diagram shows both paths converge on VectorSearchOptions.Filter
@alzarei alzarei force-pushed the remove-oldfilter-dependency branch from f844a4e to 9df93e3 Compare February 19, 2026 08:37
@markwallace-microsoft markwallace-microsoft merged commit 86e5ce7 into microsoft:feature-text-search-linq Feb 19, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation .NET Issue or Pull requests regarding .NET code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants