Skip to content

Nav expansion visitor does not visit the Contains item argument #32217

@roji

Description

@roji

Note: this issue tracks only fixing Contains. Other non-lambda operators (Skip, Take, ElementAt...) are tracked by #32312, to have two quirks for Contains and non-Contains.

When running test Nested_contains_with_Lists_and_no_inferred_type_mapping (introduced in #32214), which has the following code:

var ints = new List<int> { 1, 2, 3 };
var strings = new List<string> { "one", "two", "three" };

return AssertQuery(
    async,
    ss => ss.Set<PrimitiveCollectionsEntity>().Where(e => strings.Contains(ints.Contains(e.Int) ? "one" : "two")));

... the query tree going into nav expansion is:

DbSet<PrimitiveCollectionsEntity>()
    .Where(e => __strings_0
        .AsQueryable()
        .Contains(__ints_1
            .AsQueryable()
            .Contains(e.Int) ? "one" : "two"))

... whereas the tree coming out is:

DbSet<PrimitiveCollectionsEntity>()
    .Where(p => __strings_0
        .Contains(__ints_1
            .AsQueryable()
            .Contains(p.Int) ? "one" : "two"))

Note that the outer AsQueryable (over __strings_0) is gone, while the inner one (over __ints_1) remains.

What's happening here is this... NavigationExpandingEV works recursively on lambda arguments of operators; ProcessWhere calls into ProcessLambdaExpression, which calls into ExpandNavigationsForSource which visits the the Where predicate. This causes the Where lambda to be fully processed by the visitor, and the AsQueryable wrapping __strings_0 is removed.

However, ProcessContains does not similarly recurse into the item argument of Contains; so the AsQueryable there isn't removed.

Note that there may be other important functionality of nav expansion which is not performed here; and there are other operator aside from Contains which likely don't visit their non-lambda arguments. So there are probably other bugs hiding in here.

When this is fixed, we can remove the unwrapping of AsQueryable() from the fallback Contains translation (see #32218).

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions