diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index 791e04c0593..ba7120441e1 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -464,24 +464,24 @@ public virtual void ApplyDefaultIfEmpty() throw new InvalidOperationException(InMemoryStrings.DefaultIfEmptyAppliedAfterProjection); } - var projectionMapping = new Dictionary(); - foreach (var (projectionMember, expression) in _projectionMapping) - { - projectionMapping[projectionMember] = expression is EntityProjectionExpression entityProjectionExpression - ? MakeEntityProjectionNullable(entityProjectionExpression) - : MakeReadValueNullable(expression); - } - - _projectionMapping = projectionMapping; - var projectionMappingExpressions = _projectionMappingExpressions.Select(e => MakeReadValueNullable(e)).ToList(); - _projectionMappingExpressions.Clear(); - _projectionMappingExpressions.AddRange(projectionMappingExpressions); - _groupingParameter = null; - ServerQueryExpression = Call( EnumerableMethods.DefaultIfEmptyWithArgument.MakeGenericMethod(typeof(ValueBuffer)), ServerQueryExpression, Constant(new ValueBuffer(Enumerable.Repeat((object?)null, _projectionMappingExpressions.Count).ToArray()))); + + ReplaceProjection(_projectionMapping.ToDictionary( + kv => kv.Key, + kv => kv.Value switch + { + EntityProjectionExpression p => MakeEntityProjectionNullable(p), + + var p when !p.Type.IsNullableType() + => Coalesce( + MakeReadValueNullable(p), + p.Type.GetDefaultValueConstant()), + + var p => p + })); } /// diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 2061877c48d..b997ec7045e 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -2378,20 +2378,25 @@ [new ProjectionExpression(nullSqlExpression, "empty")], _tables.Add(dummySelectExpression); _tables.Add(joinTable); + // Go over all projected columns and make them nullable; for non-nullable value types, add a SQL COALESCE as well. var projectionMapping = new Dictionary(); - foreach (var projection in _projectionMapping) + foreach (var (projectionMember, projection) in _projectionMapping) { - var projectionToAdd = projection.Value; - if (projectionToAdd is StructuralTypeProjectionExpression typeProjection) + var newProjection = projection switch { - projectionToAdd = typeProjection.MakeNullable(); - } - else if (projectionToAdd is ColumnExpression column) + StructuralTypeProjectionExpression p => p.MakeNullable(), + ColumnExpression column => column.MakeNullable(), + var p => p + }; + + if (newProjection is SqlExpression { Type: var type } newSqlProjection && !type.IsNullableType()) { - projectionToAdd = column.MakeNullable(); + newProjection = sqlExpressionFactory.Coalesce( + newSqlProjection, + sqlExpressionFactory.Constant(type.GetDefaultValue(), type)); } - projectionMapping[projection.Key] = projectionToAdd; + projectionMapping[projectionMember] = newProjection; } // ChildIdentifiers shouldn't be required to be updated since during translation they should be empty. diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs index 00626411739..a2acda8b3e2 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs @@ -966,23 +966,21 @@ private Expression ProcessContains(NavigationExpansionExpression source, Express private NavigationExpansionExpression ProcessDefaultIfEmpty(NavigationExpansionExpression source) { - source.UpdateSource( - Expression.Call( - QueryableMethods.DefaultIfEmptyWithoutArgument.MakeGenericMethod(source.SourceElementType), - source.Source)); + // Apply any pending selector, since previous Selects can't be moved after DefaultIfEmpty (change of meaning, see #36208). + // Mark the entity(s) being selected as optional. + source = (NavigationExpansionExpression)_pendingSelectorExpandingExpressionVisitor.Visit(source); + var newStructure = SnapshotExpression(source.PendingSelector); + newStructure = _entityReferenceOptionalMarkingExpressionVisitor.Visit(newStructure); + var queryable = Reduce(source); - var pendingSelector = source.PendingSelector; - _entityReferenceOptionalMarkingExpressionVisitor.Visit(pendingSelector); - if (!pendingSelector.Type.IsNullableType()) - { - pendingSelector = Expression.Coalesce( - Expression.Convert(pendingSelector, pendingSelector.Type.MakeNullable()), - pendingSelector.Type.GetDefaultValueConstant()); - } + var result = Expression.Call( + QueryableMethods.DefaultIfEmptyWithoutArgument.MakeGenericMethod(queryable.Type.GetSequenceType()), + queryable); - source.ApplySelector(pendingSelector); + var navigationTree = new NavigationTreeExpression(newStructure); + var parameterName = GetParameterName("e"); - return source; + return new NavigationExpansionExpression(result, navigationTree, navigationTree, parameterName); } private NavigationExpansionExpression ProcessDistinct(NavigationExpansionExpression source, MethodInfo genericMethod) diff --git a/src/Shared/SharedTypeExtensions.cs b/src/Shared/SharedTypeExtensions.cs index 803525b98c9..b07eb8d053d 100644 --- a/src/Shared/SharedTypeExtensions.cs +++ b/src/Shared/SharedTypeExtensions.cs @@ -394,7 +394,6 @@ public static MethodInfo GetGenericMethod( private static readonly Dictionary CommonTypeDictionary = new() { -#pragma warning disable IDE0034 // Simplify 'default' expression - default causes default(object) { typeof(int), default(int) }, { typeof(Guid), default(Guid) }, { typeof(DateOnly), default(DateOnly) }, @@ -412,25 +411,15 @@ public static MethodInfo GetGenericMethod( { typeof(ushort), default(ushort) }, { typeof(ulong), default(ulong) }, { typeof(sbyte), default(sbyte) } -#pragma warning restore IDE0034 // Simplify 'default' expression }; public static object? GetDefaultValue( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] this Type type) - { - if (!type.IsValueType) - { - return null; - } + => type.IsNullableType() ? null : RuntimeHelpers.GetUninitializedObject(type); - // A bit of perf code to avoid calling Activator.CreateInstance for common types and - // to avoid boxing on every call. This is about 50% faster than just calling CreateInstance - // for all value types. - return CommonTypeDictionary.TryGetValue(type, out var value) - ? value - : Activator.CreateInstance(type); - } + public static ConstantExpression GetDefaultValueConstant(this Type type) + => Expression.Constant(type.GetDefaultValue(), type); [RequiresUnreferencedCode("Gets all types from the given assembly - unsafe for trimming")] public static IEnumerable GetConstructibleTypes( @@ -648,7 +637,4 @@ public static IEnumerable GetNamespaces(this Type type) } } } - - public static ConstantExpression GetDefaultValueConstant(this Type type) - => Expression.Constant(type.IsValueType ? RuntimeHelpers.GetUninitializedObject(type) : null, type); } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs index 6604b171871..986dee5ecdc 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs @@ -2573,26 +2573,26 @@ public override async Task Contains_over_entityType_should_materialize_when_comp AssertSql(); } - public override async Task Average_after_default_if_empty_does_not_throw(bool async) + public override async Task Average_after_DefaultIfEmpty_does_not_throw(bool async) { // Contains over subquery. Issue #17246. - await AssertTranslationFailed(() => base.Average_after_default_if_empty_does_not_throw(async)); + await AssertTranslationFailed(() => base.Average_after_DefaultIfEmpty_does_not_throw(async)); AssertSql(); } - public override async Task Max_after_default_if_empty_does_not_throw(bool async) + public override async Task Max_after_DefaultIfEmpty_does_not_throw(bool async) { // Contains over subquery. Issue #17246. - await AssertTranslationFailed(() => base.Max_after_default_if_empty_does_not_throw(async)); + await AssertTranslationFailed(() => base.Max_after_DefaultIfEmpty_does_not_throw(async)); AssertSql(); } - public override async Task Min_after_default_if_empty_does_not_throw(bool async) + public override async Task Min_after_DefaultIfEmpty_does_not_throw(bool async) { // Contains over subquery. Issue #17246. - await AssertTranslationFailed(() => base.Min_after_default_if_empty_does_not_throw(async)); + await AssertTranslationFailed(() => base.Min_after_DefaultIfEmpty_does_not_throw(async)); AssertSql(); } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs index 6e123d8488b..2bd74cdf376 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs @@ -202,56 +202,64 @@ public override async Task Queryable_reprojection(bool async) AssertSql(); } - public override async Task Default_if_empty_top_level(bool async) + public override async Task DefaultIfEmpty_top_level(bool async) { // Cosmos client evaluation. Issue #17246. - await AssertTranslationFailed(() => base.Default_if_empty_top_level(async)); + await AssertTranslationFailed(() => base.DefaultIfEmpty_top_level(async)); AssertSql(); } - public override async Task Join_with_default_if_empty_on_both_sources(bool async) + public override async Task Join_with_DefaultIfEmpty_on_both_sources(bool async) { // Cosmos client evaluation. Issue #17246. - await AssertTranslationFailed(() => base.Join_with_default_if_empty_on_both_sources(async)); + await AssertTranslationFailed(() => base.Join_with_DefaultIfEmpty_on_both_sources(async)); AssertSql(); } - public override async Task Default_if_empty_top_level_followed_by_projecting_constant(bool async) + public override async Task DefaultIfEmpty_top_level_followed_by_constant_Select(bool async) { // Cosmos client evaluation. Issue #17246. - await AssertTranslationFailed(() => base.Default_if_empty_top_level_followed_by_projecting_constant(async)); + await AssertTranslationFailed(() => base.DefaultIfEmpty_top_level_followed_by_constant_Select(async)); AssertSql(); } - public override async Task Default_if_empty_top_level_positive(bool async) + public override async Task DefaultIfEmpty_top_level_preceded_by_constant_Select(bool async) { // Cosmos client evaluation. Issue #17246. - await AssertTranslationFailed(() => base.Default_if_empty_top_level_positive(async)); + await AssertTranslationFailed(() => base.DefaultIfEmpty_top_level_preceded_by_constant_Select(async)); AssertSql(); } - public override async Task Default_if_empty_top_level_arg(bool async) + public override async Task DefaultIfEmpty_top_level_positive(bool async) { - await base.Default_if_empty_top_level_arg(async); + // Cosmos client evaluation. Issue #17246. + await AssertTranslationFailed(() => base.DefaultIfEmpty_top_level_positive(async)); + + AssertSql(); + } + + public override async Task DefaultIfEmpty_top_level_arg(bool async) + { + await base.DefaultIfEmpty_top_level_arg(async); AssertSql(); } - public override async Task Default_if_empty_top_level_arg_followed_by_projecting_constant(bool async) + public override async Task DefaultIfEmpty_top_level_arg_followed_by_projecting_constant(bool async) { - await base.Default_if_empty_top_level_arg_followed_by_projecting_constant(async); + await base.DefaultIfEmpty_top_level_arg_followed_by_projecting_constant(async); AssertSql(); } - public override async Task Default_if_empty_top_level_projection(bool async) + public override async Task DefaultIfEmpty_top_level_projection(bool async) { // Cosmos client evaluation. Issue #17246. - await AssertTranslationFailed(() => base.Default_if_empty_top_level_projection(async)); + await AssertTranslationFailed(() => base.DefaultIfEmpty_top_level_projection(async)); AssertSql(); } diff --git a/test/EFCore.InMemory.FunctionalTests/Query/NorthwindSelectQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/NorthwindSelectQueryInMemoryTest.cs index 647d77fe752..fb4b7dbf32c 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/NorthwindSelectQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/NorthwindSelectQueryInMemoryTest.cs @@ -14,8 +14,4 @@ public override Task () => base .SelectMany_with_collection_being_correlated_subquery_which_references_non_mapped_properties_from_inner_and_outer_entity( async)); - - public override async Task SelectMany_correlated_with_outer_3(bool async) - // DefaultIfEmpty. Issue #17536. - => await Assert.ThrowsAsync(() => base.SelectMany_correlated_with_outer_3(async)); } diff --git a/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs index 22f717ea32a..cad09e02d90 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs @@ -1899,21 +1899,21 @@ public virtual Task Min_over_default_returns_default(bool async) [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Average_after_default_if_empty_does_not_throw(bool async) + public virtual Task Average_after_DefaultIfEmpty_does_not_throw(bool async) => AssertAverage( async, ss => ss.Set().Where(o => o.OrderID == 10243).Select(o => o.OrderID).DefaultIfEmpty()); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Max_after_default_if_empty_does_not_throw(bool async) + public virtual Task Max_after_DefaultIfEmpty_does_not_throw(bool async) => AssertMax( async, ss => ss.Set().Where(o => o.OrderID == 10243).Select(o => o.OrderID).DefaultIfEmpty()); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Min_after_default_if_empty_does_not_throw(bool async) + public virtual Task Min_after_DefaultIfEmpty_does_not_throw(bool async) => AssertMin( async, ss => ss.Set().Where(o => o.OrderID == 10243).Select(o => o.OrderID).DefaultIfEmpty()); diff --git a/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs index fc017f483ce..c5891761e2d 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs @@ -2232,60 +2232,69 @@ protected class Foo [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Default_if_empty_top_level(bool async) + public virtual Task DefaultIfEmpty_top_level(bool async) => AssertQuery( async, - ss => from e in ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty() - select e); + ss => ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty()); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Join_with_default_if_empty_on_both_sources(bool async) + public virtual Task Join_with_DefaultIfEmpty_on_both_sources(bool async) => AssertQuery( async, - ss => (from e in ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty() - select e).Join( - from e in ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty() - select e, o => o, i => i, (o, i) => o), + ss => ss.Set() + .Where(c => c.EmployeeID == NonExistentID) + .DefaultIfEmpty() + .Join( + ss.Set() + .Where(c => c.EmployeeID == NonExistentID) + .DefaultIfEmpty(), + o => o, i => i, (o, i) => o), assertEmpty: true); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Default_if_empty_top_level_followed_by_projecting_constant(bool async) + public virtual Task DefaultIfEmpty_top_level_followed_by_constant_Select(bool async) => AssertQuery( async, - ss => from e in ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty() - select "Foo"); + ss => ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty().Select(_ => "Foo")); + + [ConditionalTheory] // #36208 + [MemberData(nameof(IsAsyncData))] + public virtual Task DefaultIfEmpty_top_level_preceded_by_constant_Select(bool async) + => AssertQuery( + async, + ss => ss.Set().Where(e => e.EmployeeID == NonExistentID).Select(_ => "Foo").DefaultIfEmpty()); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Default_if_empty_top_level_arg(bool async) + public virtual Task DefaultIfEmpty_top_level_arg(bool async) => AssertTranslationFailed( () => AssertQuery( async, - ss => from e in ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty(new Employee()) - select e)); + ss => ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty(new Employee()))); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Default_if_empty_top_level_arg_followed_by_projecting_constant(bool async) + public virtual Task DefaultIfEmpty_top_level_arg_followed_by_projecting_constant(bool async) => AssertTranslationFailed( () => AssertQueryScalar( async, - ss => from e in ss.Set().Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty(new Employee()) - select 42)); + ss => ss.Set() + .Where(c => c.EmployeeID == NonExistentID) + .DefaultIfEmpty(new Employee()) + .Select(_ => 42))); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Default_if_empty_top_level_positive(bool async) + public virtual Task DefaultIfEmpty_top_level_positive(bool async) => AssertQuery( async, - ss => from e in ss.Set().Where(c => c.EmployeeID > 0).DefaultIfEmpty() - select e); + ss => ss.Set().Where(c => c.EmployeeID > 0).DefaultIfEmpty()); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Default_if_empty_top_level_projection(bool async) + public virtual Task DefaultIfEmpty_top_level_projection(bool async) => AssertQueryScalar( async, ss => from e in ss.Set().Where(e => e.EmployeeID == NonExistentID).Select(e => e.EmployeeID).DefaultIfEmpty() diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs index 1a306cc84aa..b19f02b4f5b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs @@ -152,9 +152,9 @@ FROM [Orders] AS [o] """); } - public override async Task Average_after_default_if_empty_does_not_throw(bool async) + public override async Task Average_after_DefaultIfEmpty_does_not_throw(bool async) { - await base.Average_after_default_if_empty_does_not_throw(async); + await base.Average_after_DefaultIfEmpty_does_not_throw(async); AssertSql( """ @@ -170,9 +170,9 @@ FROM [Orders] AS [o] """); } - public override async Task Max_after_default_if_empty_does_not_throw(bool async) + public override async Task Max_after_DefaultIfEmpty_does_not_throw(bool async) { - await base.Max_after_default_if_empty_does_not_throw(async); + await base.Max_after_DefaultIfEmpty_does_not_throw(async); AssertSql( """ @@ -188,9 +188,9 @@ FROM [Orders] AS [o] """); } - public override async Task Min_after_default_if_empty_does_not_throw(bool async) + public override async Task Min_after_DefaultIfEmpty_does_not_throw(bool async) { - await base.Min_after_default_if_empty_does_not_throw(async); + await base.Min_after_DefaultIfEmpty_does_not_throw(async); AssertSql( """ diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs index ca5d72b7221..5129e84eb5a 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs @@ -378,9 +378,9 @@ FROM [Order Details] AS [o1] """); } - public override async Task Default_if_empty_top_level(bool async) + public override async Task DefaultIfEmpty_top_level(bool async) { - await base.Default_if_empty_top_level(async); + await base.DefaultIfEmpty_top_level(async); AssertSql( """ @@ -396,9 +396,9 @@ FROM [Employees] AS [e] """); } - public override async Task Join_with_default_if_empty_on_both_sources(bool async) + public override async Task Join_with_DefaultIfEmpty_on_both_sources(bool async) { - await base.Join_with_default_if_empty_on_both_sources(async); + await base.Join_with_DefaultIfEmpty_on_both_sources(async); AssertSql( """ @@ -425,9 +425,9 @@ FROM [Employees] AS [e2] """); } - public override async Task Default_if_empty_top_level_followed_by_projecting_constant(bool async) + public override async Task DefaultIfEmpty_top_level_followed_by_constant_Select(bool async) { - await base.Default_if_empty_top_level_followed_by_projecting_constant(async); + await base.DefaultIfEmpty_top_level_followed_by_constant_Select(async); AssertSql( """ @@ -443,9 +443,27 @@ FROM [Employees] AS [e] """); } - public override async Task Default_if_empty_top_level_positive(bool async) + public override async Task DefaultIfEmpty_top_level_preceded_by_constant_Select(bool async) { - await base.Default_if_empty_top_level_positive(async); + await base.DefaultIfEmpty_top_level_preceded_by_constant_Select(async); + + AssertSql( + """ +SELECT [e1].[c] +FROM ( + SELECT 1 AS empty +) AS [e0] +LEFT JOIN ( + SELECT N'Foo' AS [c] + FROM [Employees] AS [e] + WHERE [e].[EmployeeID] = -1 +) AS [e1] ON 1 = 1 +"""); + } + + public override async Task DefaultIfEmpty_top_level_positive(bool async) + { + await base.DefaultIfEmpty_top_level_positive(async); AssertSql( """ @@ -461,9 +479,9 @@ WHERE [e].[EmployeeID] > 0 """); } - public override async Task Default_if_empty_top_level_projection(bool async) + public override async Task DefaultIfEmpty_top_level_projection(bool async) { - await base.Default_if_empty_top_level_projection(async); + await base.DefaultIfEmpty_top_level_projection(async); AssertSql( """ @@ -6794,16 +6812,16 @@ public override async Task SelectMany_mixed(bool async) AssertSql(); } - public override async Task Default_if_empty_top_level_arg(bool async) + public override async Task DefaultIfEmpty_top_level_arg(bool async) { - await base.Default_if_empty_top_level_arg(async); + await base.DefaultIfEmpty_top_level_arg(async); AssertSql(); } - public override async Task Default_if_empty_top_level_arg_followed_by_projecting_constant(bool async) + public override async Task DefaultIfEmpty_top_level_arg_followed_by_projecting_constant(bool async) { - await base.Default_if_empty_top_level_arg_followed_by_projecting_constant(async); + await base.DefaultIfEmpty_top_level_arg_followed_by_projecting_constant(async); AssertSql(); }