diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
index eb35acf1e42..9a31e4f3b1d 100644
--- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
+++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
@@ -892,7 +892,7 @@ InExpression ProcessInExpressionValues(
if (translationMode is ParameterTranslationMode.MultipleParameters)
{
var padFactor = CalculateParameterBucketSize(values.Count, elementTypeMapping);
- var padding = (padFactor - (values.Count % padFactor)) % padFactor;
+ var padding = CalculatePadding(values.Count, padFactor);
for (var i = 0; i < padding; i++)
{
// Create parameter for value if we didn't create it yet,
@@ -1553,6 +1553,15 @@ protected virtual int CalculateParameterBucketSize(int count, RelationalTypeMapp
_ => 200,
};
+ ///
+ /// Calculates the number of padding parameters needed to align the total count to the nearest bucket size.
+ ///
+ /// Number of value parameters.
+ /// Padding factor.
+ [EntityFrameworkInternal]
+ protected virtual int CalculatePadding(int count, int padFactor)
+ => (padFactor - (count % padFactor)) % padFactor;
+
// Note that we can check parameter values for null since we cache by the parameter nullability; but we cannot do the same for bool.
private bool IsNull(SqlExpression? expression)
=> expression is SqlConstantExpression { Value: null }
diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs
index a11abe7a071..50771036605 100644
--- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs
+++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs
@@ -30,6 +30,7 @@ public class SqlServerSqlNullabilityProcessor : SqlNullabilityProcessor
private readonly ISqlServerSingletonOptions _sqlServerSingletonOptions;
private int _openJsonAliasCounter;
+ private int _totalParameterCount;
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -52,6 +53,15 @@ public SqlServerSqlNullabilityProcessor(
///
public override Expression Process(Expression queryExpression, ParametersCacheDecorator parametersDecorator)
{
+ var parametersCounter = new ParametersCounter(
+ parametersDecorator,
+ CollectionParameterTranslationMode,
+#pragma warning disable EF1001
+ (count, elementTypeMapping) => CalculatePadding(count, CalculateParameterBucketSize(count, elementTypeMapping)));
+#pragma warning restore EF1001
+ parametersCounter.Visit(queryExpression);
+ _totalParameterCount = parametersCounter.Count;
+
var result = base.Process(queryExpression, parametersDecorator);
_openJsonAliasCounter = 0;
return result;
@@ -303,14 +313,14 @@ private bool TryHandleOverLimitParameters(
out List? constantsResult,
out bool? containsNulls)
{
- var parameters = ParametersDecorator.GetAndDisableCaching();
- var values = ((IEnumerable?)parameters[valuesParameter.Name])?.Cast().ToList() ?? [];
-
// SQL Server has limit on number of parameters in a query.
// If we're over that limit, we switch to using single parameter
// and processing it through JSON functions.
- if (values.Count > MaxParameterCount)
+ if (_totalParameterCount > MaxParameterCount)
{
+ var parameters = ParametersDecorator.GetAndDisableCaching();
+ var values = ((IEnumerable?)parameters[valuesParameter.Name])?.Cast().ToList() ?? [];
+
if (_sqlServerSingletonOptions.SupportsJsonFunctions)
{
var openJsonExpression = new SqlServerOpenJsonExpression(
@@ -368,3 +378,107 @@ valuesExpression is not null
}
#pragma warning restore EF1001
}
+
+///
+/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+/// the same compatibility standards as public APIs. It may be changed or removed without notice in
+/// any release. You should only use it directly in your code with extreme caution and knowing that
+/// doing so can result in application failures when updating to a new Entity Framework Core release.
+///
+public class ParametersCounter(
+ ParametersCacheDecorator parametersDecorator,
+ ParameterTranslationMode collectionParameterTranslationMode,
+ Func bucketizationPadding) : ExpressionVisitor
+{
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual int Count { get; private set; }
+
+ private readonly HashSet _visitedSqlParameters =
+ new(EqualityComparer.Create(
+ (lhs, rhs) =>
+ ReferenceEquals(lhs, rhs)
+ || (lhs is not null && rhs is not null
+ && lhs.InvariantName == rhs.InvariantName
+ && lhs.TranslationMode == rhs.TranslationMode),
+ x => HashCode.Combine(x.InvariantName, x.TranslationMode)));
+
+ private readonly HashSet _visitedQueryParameters =
+ new(EqualityComparer.Create(
+ (lhs, rhs) =>
+ ReferenceEquals(lhs, rhs)
+ || (lhs is not null && rhs is not null
+ && lhs.Name == rhs.Name
+ && lhs.TranslationMode == rhs.TranslationMode),
+ x => HashCode.Combine(x.Name, x.TranslationMode)));
+
+ ///
+ protected override Expression VisitExtension(Expression node)
+ {
+ switch (node)
+ {
+ case ValuesExpression { ValuesParameter: { } valuesParameter }:
+ ProcessCollectionParameter(valuesParameter, bucketization: false);
+ break;
+
+ case InExpression { ValuesParameter: { } valuesParameter }:
+ ProcessCollectionParameter(valuesParameter, bucketization: true);
+ break;
+
+ case FromSqlExpression { Arguments: QueryParameterExpression queryParameter }:
+ if (_visitedQueryParameters.Add(queryParameter))
+ {
+ var parameters = parametersDecorator.GetAndDisableCaching();
+ Count += ((object?[])parameters[queryParameter.Name]!).Length;
+ }
+ break;
+
+ case SqlParameterExpression sqlParameterExpression:
+ if (_visitedSqlParameters.Add(sqlParameterExpression))
+ {
+ Count++;
+ }
+ break;
+ }
+
+ return base.VisitExtension(node);
+ }
+
+ private void ProcessCollectionParameter(SqlParameterExpression sqlParameterExpression, bool bucketization)
+ {
+ if (!_visitedSqlParameters.Add(sqlParameterExpression))
+ {
+ return;
+ }
+
+ switch (sqlParameterExpression.TranslationMode ?? collectionParameterTranslationMode)
+ {
+ case ParameterTranslationMode.MultipleParameters:
+ var parameters = parametersDecorator.GetAndDisableCaching();
+ var count = ((IEnumerable?)parameters[sqlParameterExpression.Name])?.Cast().Count() ?? 0;
+ Count += count;
+
+ if (bucketization)
+ {
+ var elementTypeMapping = (RelationalTypeMapping)sqlParameterExpression.TypeMapping!.ElementTypeMapping!;
+ Count += bucketizationPadding(count, elementTypeMapping);
+ }
+
+ break;
+
+ case ParameterTranslationMode.Parameter:
+ Count++;
+ break;
+
+ case ParameterTranslationMode.Constant:
+ break;
+
+ default:
+ throw new UnreachableException();
+ }
+ }
+}
diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs
index 63fa6177209..11ae7ef7467 100644
--- a/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs
@@ -825,10 +825,42 @@ public override async Task Parameter_collection_Count_with_column_predicate_with
public override Task Parameter_collection_Count_with_huge_number_of_values()
=> base.Parameter_collection_Count_with_huge_number_of_values();
+ // nothing to test here
+ public override Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations()
+ => base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations();
+
+ // nothing to test here
+ public override Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants()
+ => base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ // nothing to test here
+ public override Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter()
+ => base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ // nothing to test here
+ public override Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ => base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
// nothing to test here
public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values()
=> base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values();
+ // nothing to test here
+ public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations()
+ => base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations();
+
+ // nothing to test here
+ public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter()
+ => base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ // nothing to test here
+ public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants()
+ => base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ // nothing to test here
+ public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ => base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
public override async Task Static_readonly_collection_List_of_ints_Contains_int()
{
await base.Static_readonly_collection_List_of_ints_Contains_int();
diff --git a/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs
index ad05ecf5290..8c43f76ee17 100644
--- a/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs
+++ b/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs
@@ -519,6 +519,134 @@ public virtual Task Parameter_collection_Count_with_huge_number_of_values()
return AssertQuery(ss => ss.Set().Where(c => ids.Count(i => i > c.Id) > 0));
}
+ [ConditionalFact]
+ public virtual Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations()
+ {
+ if (NumberOfValuesForHugeParameterCollectionTests is null)
+ {
+ return Task.CompletedTask;
+ }
+
+ var extra1 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra2 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra3 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra4 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra5 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var ids = new[] { 2, 999 };
+
+
+ return AssertQuery(ss => ss.Set()
+ .Where(c => ids.Count(i => i > c.Id) > 0)
+ .Where(c => extra1.Count(i => i > c.Id) > 0)
+ .Where(c => extra2.Count(i => i > c.Id) > 0)
+ .Where(c => extra3.Count(i => i > c.Id) > 0)
+ .Where(c => extra4.Count(i => i > c.Id) > 0)
+ .Where(c => extra5.Count(i => i > c.Id) > 0));
+ }
+
+ [ConditionalFact]
+ public virtual Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ if (NumberOfValuesForHugeParameterCollectionTests is null)
+ {
+ return Task.CompletedTask;
+ }
+
+ var extra = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var ids = new[] { 2, 999 };
+
+
+ return AssertQuery(ss => ss.Set()
+ .Where(c => ids.Count(i => i > c.Id) > 0)
+ .Where(c => extra.Count(i => i > c.Id) > 0)
+ .Where(c => extra.Count(i => i > c.Id) > 0)
+ .Where(c => extra.Count(i => i > c.Id) > 0)
+ .Where(c => extra.Count(i => i > c.Id) > 0)
+ .Where(c => extra.Count(i => i > c.Id) > 0));
+ }
+
+ [ConditionalFact]
+ public virtual Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ if (NumberOfValuesForHugeParameterCollectionTests is null)
+ {
+ return Task.CompletedTask;
+ }
+
+ var extra1 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra2 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra3 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra4 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra5 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var ids = new[] { 2, 999 };
+
+
+ return AssertQuery(
+ ss => ss.Set()
+ .Where(c => ids.Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra1).Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra2).Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra3).Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra4).Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra5).Count(i => i > c.Id) > 0),
+ ss => ss.Set()
+ .Where(c => ids.Count(i => i > c.Id) > 0)
+ .Where(c => extra1.Count(i => i > c.Id) > 0)
+ .Where(c => extra2.Count(i => i > c.Id) > 0)
+ .Where(c => extra3.Count(i => i > c.Id) > 0)
+ .Where(c => extra4.Count(i => i > c.Id) > 0)
+ .Where(c => extra5.Count(i => i > c.Id) > 0));
+ }
+
+ [ConditionalFact]
+ public virtual Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ if (NumberOfValuesForHugeParameterCollectionTests is null)
+ {
+ return Task.CompletedTask;
+ }
+
+ var extra1 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra2 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra3 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra4 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra5 = Enumerable.Range(1000, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var ids = new[] { 2, 999 };
+
+
+ return AssertQuery(
+ ss => ss.Set()
+ .Where(c => ids.Count(i => i > c.Id) > 0)
+ // This is intentional. We want to "see" the constant parameters first
+ // and only then the non-constant parameters to verify the counting
+ // work as expected.
+ .Where(c => EF.Constant(extra1).Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra2).Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra3).Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra4).Count(i => i > c.Id) > 0)
+ .Where(c => EF.Constant(extra5).Count(i => i > c.Id) > 0)
+ .Where(c => extra1.Count(i => i > c.Id) > 0)
+ .Where(c => extra2.Count(i => i > c.Id) > 0)
+ .Where(c => extra3.Count(i => i > c.Id) > 0)
+ .Where(c => extra4.Count(i => i > c.Id) > 0)
+ .Where(c => extra5.Count(i => i > c.Id) > 0),
+ ss => ss.Set()
+ .Where(c => ids.Count(i => i > c.Id) > 0)
+ // This is intentional. We want to "see" the constant parameters first
+ // and only then the non-constant parameters to verify the counting
+ // work as expected.
+ .Where(c => extra1.Count(i => i > c.Id) > 0)
+ .Where(c => extra2.Count(i => i > c.Id) > 0)
+ .Where(c => extra3.Count(i => i > c.Id) > 0)
+ .Where(c => extra4.Count(i => i > c.Id) > 0)
+ .Where(c => extra5.Count(i => i > c.Id) > 0)
+ .Where(c => extra1.Count(i => i > c.Id) > 0)
+ .Where(c => extra2.Count(i => i > c.Id) > 0)
+ .Where(c => extra3.Count(i => i > c.Id) > 0)
+ .Where(c => extra4.Count(i => i > c.Id) > 0)
+ .Where(c => extra5.Count(i => i > c.Id) > 0));
+ }
+
[ConditionalFact]
public virtual async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values()
{
@@ -534,6 +662,184 @@ public virtual async Task Parameter_collection_of_ints_Contains_int_with_huge_nu
await AssertQuery(ss => ss.Set().Where(c => !ints.Contains(c.Int)));
}
+ [ConditionalFact]
+ public virtual async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations()
+ {
+ if (NumberOfValuesForHugeParameterCollectionTests is null)
+ {
+ return;
+ }
+
+ var extra1 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra2 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra3 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra4 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra5 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var ints = new[] { 10, 999 };
+
+ await AssertQuery(ss => ss.Set()
+ .Where(c => ints.Contains(c.Int))
+ .Where(c => extra1.Contains(c.Int))
+ .Where(c => extra2.Contains(c.Int))
+ .Where(c => extra3.Contains(c.Int))
+ .Where(c => extra4.Contains(c.Int))
+ .Where(c => extra5.Contains(c.Int)));
+ await AssertQuery(ss => ss.Set()
+ .Where(c => !ints.Contains(c.Int))
+ .Where(c => !extra1.Contains(c.Int))
+ .Where(c => !extra2.Contains(c.Int))
+ .Where(c => !extra3.Contains(c.Int))
+ .Where(c => !extra4.Contains(c.Int))
+ .Where(c => !extra5.Contains(c.Int)));
+ }
+
+ [ConditionalFact]
+ public virtual async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ if (NumberOfValuesForHugeParameterCollectionTests is null)
+ {
+ return;
+ }
+
+ var extra = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var ints = new[] { 10, 999 };
+
+ await AssertQuery(ss => ss.Set()
+ .Where(c => ints.Contains(c.Int))
+ .Where(c => extra.Contains(c.Int))
+ .Where(c => extra.Contains(c.Int))
+ .Where(c => extra.Contains(c.Int))
+ .Where(c => extra.Contains(c.Int))
+ .Where(c => extra.Contains(c.Int)));
+ await AssertQuery(ss => ss.Set()
+ .Where(c => !ints.Contains(c.Int))
+ .Where(c => !extra.Contains(c.Int))
+ .Where(c => !extra.Contains(c.Int))
+ .Where(c => !extra.Contains(c.Int))
+ .Where(c => !extra.Contains(c.Int))
+ .Where(c => !extra.Contains(c.Int)));
+ }
+
+ [ConditionalFact]
+ public virtual async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ if (NumberOfValuesForHugeParameterCollectionTests is null)
+ {
+ return;
+ }
+
+ var extra1 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra2 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra3 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra4 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra5 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var ints = new[] { 10, 999 };
+
+ await AssertQuery(
+ ss => ss.Set()
+ .Where(c => ints.Contains(c.Int))
+ .Where(c => EF.Constant(extra1).Contains(c.Int))
+ .Where(c => EF.Constant(extra2).Contains(c.Int))
+ .Where(c => EF.Constant(extra3).Contains(c.Int))
+ .Where(c => EF.Constant(extra4).Contains(c.Int))
+ .Where(c => EF.Constant(extra5).Contains(c.Int)),
+ ss => ss.Set()
+ .Where(c => ints.Contains(c.Int))
+ .Where(c => extra1.Contains(c.Int))
+ .Where(c => extra2.Contains(c.Int))
+ .Where(c => extra3.Contains(c.Int))
+ .Where(c => extra4.Contains(c.Int))
+ .Where(c => extra5.Contains(c.Int)));
+ await AssertQuery(
+ ss => ss.Set()
+ .Where(c => !ints.Contains(c.Int))
+ .Where(c => !EF.Constant(extra1).Contains(c.Int))
+ .Where(c => !EF.Constant(extra2).Contains(c.Int))
+ .Where(c => !EF.Constant(extra3).Contains(c.Int))
+ .Where(c => !EF.Constant(extra4).Contains(c.Int))
+ .Where(c => !EF.Constant(extra5).Contains(c.Int)),
+ ss => ss.Set()
+ .Where(c => !ints.Contains(c.Int))
+ .Where(c => !extra1.Contains(c.Int))
+ .Where(c => !extra2.Contains(c.Int))
+ .Where(c => !extra3.Contains(c.Int))
+ .Where(c => !extra4.Contains(c.Int))
+ .Where(c => !extra5.Contains(c.Int)));
+ }
+
+ [ConditionalFact]
+ public virtual async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ if (NumberOfValuesForHugeParameterCollectionTests is null)
+ {
+ return;
+ }
+
+ var extra1 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra2 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra3 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra4 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var extra5 = Enumerable.Range(10, (int)NumberOfValuesForHugeParameterCollectionTests / 5);
+ var ints = new[] { 10, 999 };
+
+ await AssertQuery(
+ ss => ss.Set()
+ .Where(c => ints.Contains(c.Int))
+ // This is intentional. We want to "see" the constant parameters first
+ // and only then the non-constant parameters to verify the counting
+ // work as expected.
+ .Where(c => EF.Constant(extra1).Contains(c.Int))
+ .Where(c => EF.Constant(extra2).Contains(c.Int))
+ .Where(c => EF.Constant(extra3).Contains(c.Int))
+ .Where(c => EF.Constant(extra4).Contains(c.Int))
+ .Where(c => EF.Constant(extra5).Contains(c.Int))
+ .Where(c => extra1.Contains(c.Int))
+ .Where(c => extra2.Contains(c.Int))
+ .Where(c => extra3.Contains(c.Int))
+ .Where(c => extra4.Contains(c.Int))
+ .Where(c => extra5.Contains(c.Int)),
+ ss => ss.Set()
+ .Where(c => ints.Contains(c.Int))
+ .Where(c => extra1.Contains(c.Int))
+ .Where(c => extra2.Contains(c.Int))
+ .Where(c => extra3.Contains(c.Int))
+ .Where(c => extra4.Contains(c.Int))
+ .Where(c => extra5.Contains(c.Int))
+ .Where(c => extra1.Contains(c.Int))
+ .Where(c => extra2.Contains(c.Int))
+ .Where(c => extra3.Contains(c.Int))
+ .Where(c => extra4.Contains(c.Int))
+ .Where(c => extra5.Contains(c.Int)));
+ await AssertQuery(
+ ss => ss.Set()
+ .Where(c => !ints.Contains(c.Int))
+ // This is intentional. We want to "see" the constant parameters first
+ // and only then the non-constant parameters to verify the counting
+ // work as expected.
+ .Where(c => !EF.Constant(extra1).Contains(c.Int))
+ .Where(c => !EF.Constant(extra2).Contains(c.Int))
+ .Where(c => !EF.Constant(extra3).Contains(c.Int))
+ .Where(c => !EF.Constant(extra4).Contains(c.Int))
+ .Where(c => !EF.Constant(extra5).Contains(c.Int))
+ .Where(c => !extra1.Contains(c.Int))
+ .Where(c => !extra2.Contains(c.Int))
+ .Where(c => !extra3.Contains(c.Int))
+ .Where(c => !extra4.Contains(c.Int))
+ .Where(c => !extra5.Contains(c.Int)),
+ ss => ss.Set()
+ .Where(c => !ints.Contains(c.Int))
+ .Where(c => !extra1.Contains(c.Int))
+ .Where(c => !extra2.Contains(c.Int))
+ .Where(c => !extra3.Contains(c.Int))
+ .Where(c => !extra4.Contains(c.Int))
+ .Where(c => !extra5.Contains(c.Int))
+ .Where(c => !extra1.Contains(c.Int))
+ .Where(c => !extra2.Contains(c.Int))
+ .Where(c => !extra3.Contains(c.Int))
+ .Where(c => !extra4.Contains(c.Int))
+ .Where(c => !extra5.Contains(c.Int)));
+ }
+
[ConditionalFact]
public virtual async Task Static_readonly_collection_List_of_ints_Contains_int()
{
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs
index c3ed178e2da..f4f6f3b2669 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs
@@ -838,7 +838,37 @@ public override async Task Parameter_collection_Count_with_huge_number_of_values
{
await base.Parameter_collection_Count_with_huge_number_of_values();
- Assert.Contains("VALUES", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("VALUES (2)", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations();
+
+ Assert.Contains("VALUES (2)", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ Assert.Contains("@ids1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ids2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ Assert.Contains("@ids1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ids2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
+ Assert.Contains("VALUES (2)", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
}
public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values()
@@ -849,6 +879,42 @@ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_n
Assert.DoesNotContain("OPENJSON", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
}
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations();
+
+ Assert.DoesNotContain("OPENJSON", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.DoesNotContain("OPENJSON", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
+ Assert.DoesNotContain("OPENJSON", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.DoesNotContain("OPENJSON", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
public override async Task Static_readonly_collection_List_of_ints_Contains_int()
{
await base.Static_readonly_collection_List_of_ints_Contains_int();
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServer160Test.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServer160Test.cs
index 0bf1abae92c..88829d0e8cf 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServer160Test.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServer160Test.cs
@@ -835,6 +835,36 @@ public override async Task Parameter_collection_Count_with_huge_number_of_values
Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
}
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations();
+
+ Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ Assert.Contains("@ids1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ids2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ Assert.Contains("@ids1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ids2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
+ Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values()
{
await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values();
@@ -843,6 +873,42 @@ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_n
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
}
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations();
+
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
public override async Task Static_readonly_collection_List_of_ints_Contains_int()
{
await base.Static_readonly_collection_List_of_ints_Contains_int();
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerJsonTypeTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerJsonTypeTest.cs
index 209b099eb8b..0e1a1a23a7d 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerJsonTypeTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerJsonTypeTest.cs
@@ -102,6 +102,36 @@ public override async Task Parameter_collection_Count_with_huge_number_of_values
Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
}
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations();
+
+ Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ Assert.Contains("@ids1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ids2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ Assert.Contains("@ids1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ids2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
+ Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values()
{
await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values();
@@ -110,6 +140,42 @@ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_n
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
}
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations();
+
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
public override async Task Inline_collection_of_ints_Contains()
{
await base.Inline_collection_of_ints_Contains();
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs
index 6feec54c4d0..20ae846bfa4 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs
@@ -858,6 +858,36 @@ public override async Task Parameter_collection_Count_with_huge_number_of_values
Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
}
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations();
+
+ Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ Assert.Contains("@ids1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ids2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ Assert.Contains("@ids1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ids2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
+ Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ }
+
public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values()
{
await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values();
@@ -866,6 +896,42 @@ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_n
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
}
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations();
+
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("@ints1=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ Assert.Contains("@ints2=", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
+ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ {
+ await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
+ Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
+ }
+
public override async Task Static_readonly_collection_List_of_ints_Contains_int()
{
await base.Static_readonly_collection_List_of_ints_Contains_int();
diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs
index 7abd358bbf0..37cb747bac5 100644
--- a/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs
+++ b/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs
@@ -843,10 +843,42 @@ SELECT COUNT(*)
public override Task Parameter_collection_Count_with_huge_number_of_values()
=> base.Parameter_collection_Count_with_huge_number_of_values();
+ // nothing to test here
+ public override Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations()
+ => base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations();
+
+ // nothing to test here
+ public override Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants()
+ => base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ // nothing to test here
+ public override Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter()
+ => base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ // nothing to test here
+ public override Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ => base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
// nothing to test here
public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values()
=> base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values();
+ // nothing to test here
+ public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations()
+ => base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations();
+
+ // nothing to test here
+ public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter()
+ => base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter();
+
+ // nothing to test here
+ public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants()
+ => base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants();
+
+ // nothing to test here
+ public override Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants()
+ => base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
+
public override async Task Static_readonly_collection_List_of_ints_Contains_int()
{
await base.Static_readonly_collection_List_of_ints_Contains_int();