From b9e62ff165515cb054afb5a33d1256884b8d4ded Mon Sep 17 00:00:00 2001 From: Jiri Cincura Date: Wed, 17 Dec 2025 14:10:23 +0100 Subject: [PATCH] Fix handling of Contains on IReadOnlySet and custom IReadOnlyCollection. --- ...yableMethodNormalizingExpressionVisitor.cs | 7 +-- ...thwindAggregateOperatorsQueryCosmosTest.cs | 8 +++- .../PrimitiveCollectionsQueryCosmosTest.cs | 44 +++++++++++++++++ .../PrimitiveCollectionsQueryTestBase.cs | 31 ++++++++++++ ...imitiveCollectionsQueryOldSqlServerTest.cs | 48 +++++++++++++++++++ ...imitiveCollectionsQuerySqlServer160Test.cs | 48 +++++++++++++++++++ ...veCollectionsQuerySqlServerJsonTypeTest.cs | 48 +++++++++++++++++++ .../PrimitiveCollectionsQuerySqlServerTest.cs | 48 +++++++++++++++++++ .../PrimitiveCollectionsQuerySqliteTest.cs | 48 +++++++++++++++++++ 9 files changed, 325 insertions(+), 5 deletions(-) diff --git a/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs b/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs index e15dbc5b400..9b87e7d92fc 100644 --- a/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs @@ -170,9 +170,10 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp visitedExpression = TryConvertEnumerableToQueryable(methodCallExpression); } - if (method.DeclaringType is { IsGenericType: true } - && method.DeclaringType.TryGetElementType(typeof(ICollection<>)) is not null - && method.Name == nameof(ICollection<>.Contains)) + if (method.Name == nameof(ICollection<>.Contains) + && method.DeclaringType is { IsGenericType: true } + && (method.DeclaringType.TryGetElementType(typeof(ICollection<>)) is not null + || method.DeclaringType.TryGetElementType(typeof(IReadOnlyCollection<>)) is not null)) { visitedExpression = TryConvertCollectionContainsToQueryableContains(methodCallExpression); } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs index 28a25a29817..62db3a71ee3 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs @@ -2175,9 +2175,11 @@ public override Task IImmutableSet_Contains_with_parameter(bool async) AssertSql( """ +@ids='["ALFKI"]' + SELECT VALUE c FROM root c -WHERE (c["id"] = "ALFKI") +WHERE ARRAY_CONTAINS(@ids, c["id"]) """); }); @@ -2189,9 +2191,11 @@ public override Task IReadOnlySet_Contains_with_parameter(bool async) AssertSql( """ +@ids='["ALFKI"]' + SELECT VALUE c FROM root c -WHERE (c["id"] = "ALFKI") +WHERE ARRAY_CONTAINS(@ids, c["id"]) """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs index 8c9614e01ea..07337713dcf 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs @@ -597,6 +597,50 @@ WHERE ARRAY_CONTAINS(@ints, c["Int"]) """ @ints='[10,999]' +SELECT VALUE c +FROM root c +WHERE NOT(ARRAY_CONTAINS(@ints, c["Int"])) +"""); + } + + public override async Task Parameter_collection_IReadOnlySet_of_ints_Contains_int() + { + await base.Parameter_collection_IReadOnlySet_of_ints_Contains_int(); + + AssertSql( + """ +@ints='[10,999]' + +SELECT VALUE c +FROM root c +WHERE ARRAY_CONTAINS(@ints, c["Int"]) +""", + // + """ +@ints='[10,999]' + +SELECT VALUE c +FROM root c +WHERE NOT(ARRAY_CONTAINS(@ints, c["Int"])) +"""); + } + + public override async Task Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int() + { + await base.Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int(); + + AssertSql( + """ +@ints='[10,999]' + +SELECT VALUE c +FROM root c +WHERE ARRAY_CONTAINS(@ints, c["Int"]) +""", + // + """ +@ints='[10,999]' + SELECT VALUE c FROM root c WHERE NOT(ARRAY_CONTAINS(@ints, c["Int"])) diff --git a/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs index ba7a79ab7cf..cd91195e6ab 100644 --- a/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Frozen; using System.Collections.Immutable; @@ -294,6 +295,25 @@ public virtual async Task Parameter_collection_ImmutableArray_of_ints_Contains_i await AssertQuery(ss => ss.Set().Where(c => !ints.Contains(c.Int))); } + [ConditionalFact] + public virtual async Task Parameter_collection_IReadOnlySet_of_ints_Contains_int() + { + // IReadOnlySet has Contains defined directly on itself + IReadOnlySet ints = new HashSet { 10, 999 }; + + await AssertQuery(ss => ss.Set().Where(c => ints.Contains(c.Int))); + await AssertQuery(ss => ss.Set().Where(c => !ints.Contains(c.Int))); + } + + [ConditionalFact] + public virtual async Task Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int() + { + var ints = new ReadOnlyCollectionWithContains(10, 999); + + await AssertQuery(ss => ss.Set().Where(c => ints.Contains(c.Int))); + await AssertQuery(ss => ss.Set().Where(c => !ints.Contains(c.Int))); + } + [ConditionalFact] public virtual async Task Parameter_collection_of_ints_Contains_nullable_int() { @@ -1835,3 +1855,14 @@ private static IReadOnlyList CreatePrimitiveArrayEnt }; } } + +// Keep it outside so it does not inherit the TFixture. +internal class ReadOnlyCollectionWithContains(params T[] items) : IReadOnlyCollection +{ + public int Count => items.Length; + + public bool Contains(T item) => items.Contains(item); + + public IEnumerator GetEnumerator() => items.AsEnumerable().GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs index 0c63d5646cb..6c9cb5bb59b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs @@ -571,6 +571,54 @@ WHERE [p].[Int] IN (@ints1, @ints2) @ints1='10' @ints2='999' +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_IReadOnlySet_of_ints_Contains_int() + { + await base.Parameter_collection_IReadOnlySet_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int() + { + await base.Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] FROM [PrimitiveCollectionsEntity] AS [p] WHERE [p].[Int] NOT IN (@ints1, @ints2) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServer160Test.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServer160Test.cs index 8316226faf5..aee0ce02016 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServer160Test.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServer160Test.cs @@ -579,6 +579,54 @@ WHERE [p].[Int] IN (@ints1, @ints2) @ints1='10' @ints2='999' +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_IReadOnlySet_of_ints_Contains_int() + { + await base.Parameter_collection_IReadOnlySet_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int() + { + await base.Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] FROM [PrimitiveCollectionsEntity] AS [p] WHERE [p].[Int] NOT IN (@ints1, @ints2) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerJsonTypeTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerJsonTypeTest.cs index 675be39bdd8..86888a6b8fc 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerJsonTypeTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerJsonTypeTest.cs @@ -723,6 +723,54 @@ WHERE [p].[Int] IN (@ints1, @ints2) @ints1='10' @ints2='999' +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_IReadOnlySet_of_ints_Contains_int() + { + await base.Parameter_collection_IReadOnlySet_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int() + { + await base.Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] FROM [PrimitiveCollectionsEntity] AS [p] WHERE [p].[Int] NOT IN (@ints1, @ints2) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs index c5f08aa72bd..b7ccb650ecb 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs @@ -602,6 +602,54 @@ WHERE [p].[Int] IN (@ints1, @ints2) @ints1='10' @ints2='999' +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_IReadOnlySet_of_ints_Contains_int() + { + await base.Parameter_collection_IReadOnlySet_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int() + { + await base.Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] +FROM [PrimitiveCollectionsEntity] AS [p] +WHERE [p].[Int] IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[NullableWrappedId], [p].[NullableWrappedIdWithNullableComparer], [p].[String], [p].[Strings], [p].[WrappedId] FROM [PrimitiveCollectionsEntity] AS [p] WHERE [p].[Int] NOT IN (@ints1, @ints2) diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs index 1c94be49766..85afb0cf774 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs @@ -590,6 +590,54 @@ public override async Task Parameter_collection_ImmutableArray_of_ints_Contains_ @ints1='10' @ints2='999' +SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."NullableWrappedId", "p"."NullableWrappedIdWithNullableComparer", "p"."String", "p"."Strings", "p"."WrappedId" +FROM "PrimitiveCollectionsEntity" AS "p" +WHERE "p"."Int" NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_IReadOnlySet_of_ints_Contains_int() + { + await base.Parameter_collection_IReadOnlySet_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."NullableWrappedId", "p"."NullableWrappedIdWithNullableComparer", "p"."String", "p"."Strings", "p"."WrappedId" +FROM "PrimitiveCollectionsEntity" AS "p" +WHERE "p"."Int" IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + +SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."NullableWrappedId", "p"."NullableWrappedIdWithNullableComparer", "p"."String", "p"."Strings", "p"."WrappedId" +FROM "PrimitiveCollectionsEntity" AS "p" +WHERE "p"."Int" NOT IN (@ints1, @ints2) +"""); + } + + public override async Task Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int() + { + await base.Parameter_collection_ReadOnlyCollectionWithContains_of_ints_Contains_int(); + + AssertSql( + """ +@ints1='10' +@ints2='999' + +SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."NullableWrappedId", "p"."NullableWrappedIdWithNullableComparer", "p"."String", "p"."Strings", "p"."WrappedId" +FROM "PrimitiveCollectionsEntity" AS "p" +WHERE "p"."Int" IN (@ints1, @ints2) +""", + // + """ +@ints1='10' +@ints2='999' + SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."NullableWrappedId", "p"."NullableWrappedIdWithNullableComparer", "p"."String", "p"."Strings", "p"."WrappedId" FROM "PrimitiveCollectionsEntity" AS "p" WHERE "p"."Int" NOT IN (@ints1, @ints2)