Skip to content

Commit eca4896

Browse files
committed
Fix to #35024 - Query could not be translated when using a static ICollection/IList field
Problem was that when converting primitive collection to inline query root we were not matching the expression if it was constant wrapped in convert. Fix is to remove convert for the purpose of pattern match for the transformation. Fixes #35024
1 parent 507e7f1 commit eca4896

File tree

5 files changed

+47
-1
lines changed

5 files changed

+47
-1
lines changed

src/EFCore/Query/QueryRootProcessor.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
8585

8686
private Expression VisitQueryRootCandidate(Expression expression, Type elementClrType)
8787
{
88-
switch (expression)
88+
switch (RemoveConvert(expression))
8989
{
9090
// An array containing only constants is represented as a ConstantExpression with the array as the value.
9191
// Convert that into a NewArrayExpression for use with InlineQueryRootExpression
@@ -122,6 +122,11 @@ when listInitExpression.Type.TryGetElementType(typeof(IList<>)) is not null
122122
default:
123123
return Visit(expression);
124124
}
125+
126+
static Expression RemoveConvert(Expression e)
127+
=> e is UnaryExpression { NodeType: ExpressionType.Convert or ExpressionType.ConvertChecked } unary
128+
? RemoveConvert(unary.Operand)
129+
: e;
125130
}
126131

127132
/// <summary>

test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs

+8
Original file line numberDiff line numberDiff line change
@@ -2068,6 +2068,14 @@ public override async Task Contains_with_local_anonymous_type_array_closure(bool
20682068
AssertSql();
20692069
}
20702070

2071+
public override async Task Contains_with_static_IList(bool async)
2072+
{
2073+
// Contains over subquery. Issue #17246.
2074+
await AssertTranslationFailed(() => base.Contains_with_static_IList(async));
2075+
2076+
AssertSql();
2077+
}
2078+
20712079
public override async Task OfType_Select(bool async)
20722080
{
20732081
// Contains over subquery. Issue #17246.

test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs

+9
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,15 @@ public virtual Task Contains_with_local_anonymous_type_array_closure(bool async)
13611361
ss => ss.Set<OrderDetail>().Where(o => ids.Contains(new { Id1 = o.OrderID, Id2 = o.ProductID })));
13621362
}
13631363

1364+
private static readonly IList<string> StaticIds = new List<string> { "ALFKI", "ANATR" };
1365+
1366+
[ConditionalTheory]
1367+
[MemberData(nameof(IsAsyncData))]
1368+
public virtual Task Contains_with_static_IList(bool async)
1369+
=> AssertQuery(
1370+
async,
1371+
ss => ss.Set<Customer>().Where(c => StaticIds.Contains(c.CustomerID)));
1372+
13641373
[ConditionalTheory]
13651374
[MemberData(nameof(IsAsyncData))]
13661375
public virtual Task OfType_Select(bool async)

test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs

+12
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,18 @@ public override async Task Contains_with_local_anonymous_type_array_closure(bool
23032303
AssertSql();
23042304
}
23052305

2306+
public override async Task Contains_with_static_IList(bool async)
2307+
{
2308+
await base.Contains_with_static_IList(async);
2309+
2310+
AssertSql(
2311+
"""
2312+
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
2313+
FROM [Customers] AS [c]
2314+
WHERE [c].[CustomerID] IN (N'ALFKI', N'ANATR')
2315+
""");
2316+
}
2317+
23062318
public override async Task OfType_Select(bool async)
23072319
{
23082320
await base.OfType_Select(async);

test/EFCore.Sqlite.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqliteTest.cs

+12
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,18 @@ public override async Task Contains_with_local_anonymous_type_array_closure(bool
123123
public override async Task Contains_with_local_tuple_array_closure(bool async)
124124
=> await AssertTranslationFailed(() => base.Contains_with_local_tuple_array_closure(async));
125125

126+
public override async Task Contains_with_static_IList(bool async)
127+
{
128+
await base.Contains_with_static_IList(async);
129+
130+
AssertSql(
131+
"""
132+
SELECT "c"."CustomerID", "c"."Address", "c"."City", "c"."CompanyName", "c"."ContactName", "c"."ContactTitle", "c"."Country", "c"."Fax", "c"."Phone", "c"."PostalCode", "c"."Region"
133+
FROM "Customers" AS "c"
134+
WHERE "c"."CustomerID" IN ('ALFKI', 'ANATR')
135+
""");
136+
}
137+
126138
public override async Task Contains_inside_aggregate_function_with_GroupBy(bool async)
127139
{
128140
await base.Contains_inside_aggregate_function_with_GroupBy(async);

0 commit comments

Comments
 (0)