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();