From 1bd4e85c8dbe62d4c73bd216826bbfd18f126dec Mon Sep 17 00:00:00 2001 From: Maurycy Markowski Date: Wed, 2 Oct 2019 11:38:40 -0700 Subject: [PATCH] Miscellaneous query test fixes resolves #14550 resolves #15164 resolves #15994 resolves #16722 added regression tests for #14671 added regression test for #17852 converted remaining tests in Gears of War into AssertQuery pattern (part of #12501) --- ...ingExpressionVisitor.ExpressionVisitors.cs | 1 - .../ComplexNavigationsQueryInMemoryTest.cs | 6 + .../Query/ComplexNavigationsQueryTestBase.cs | 241 +-- .../ComplexNavigationsWeakQueryTestBase.cs | 26 +- .../Query/GearsOfWarQueryTestBase.cs | 1626 ++++++++--------- .../SimpleQueryTestBase.ResultOperators.cs | 21 + .../ComplexNavigationsQuerySqlServerTest.cs | 62 +- .../Query/GearsOfWarQuerySqlServerTest.cs | 535 +++--- ...impleQuerySqlServerTest.ResultOperators.cs | 15 + .../ComplexNavigationsQuerySqliteTest.cs | 6 +- 10 files changed, 1314 insertions(+), 1225 deletions(-) diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs index 02aba9698e6..f21b0ffd795 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; diff --git a/test/EFCore.InMemory.FunctionalTests/Query/ComplexNavigationsQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/ComplexNavigationsQueryInMemoryTest.cs index f043039dee6..1a290d4432b 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/ComplexNavigationsQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/ComplexNavigationsQueryInMemoryTest.cs @@ -20,5 +20,11 @@ public override Task Complex_query_with_optional_navigations_and_client_side_eva { return base.Complex_query_with_optional_navigations_and_client_side_evaluation(isAsync); } + + [ConditionalFact(Skip = "issue #18194")] + public override void Member_pushdown_chain_3_levels_deep_entity() + { + base.Member_pushdown_chain_3_levels_deep_entity(); + } } } diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs index a442174b9b7..f57912a7a08 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs @@ -1437,48 +1437,29 @@ select new e => (e.Name, e.Id)); } - [ConditionalFact] - public virtual void Optional_navigation_projected_into_DTO() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Optional_navigation_projected_into_DTO(bool isAsync) { - using (var context = CreateContext()) - { - var actual = Fixture.QueryAsserter.SetSourceCreator(context).Set().Select( - e => new MyOuterDto - { - Id = e.Id, - Name = e.Name, - Inner = e.OneToOne_Optional_FK1 != null - ? new MyInnerDto { Id = (int?)e.OneToOne_Optional_FK1.Id, Name = e.OneToOne_Optional_FK1.Name } - : null - }).ToList().OrderBy(e => e.Id + " " + e.Name + " " + e.Inner).ToList(); - - var expected = Fixture.QueryAsserter.ExpectedData.Set().Select( + return AssertQuery( + isAsync, + ss => ss.Set().Select( e => new MyOuterDto { Id = e.Id, Name = e.Name, Inner = e.OneToOne_Optional_FK1 != null - ? new MyInnerDto { Id = (int?)e.OneToOne_Optional_FK1.Id, Name = e.OneToOne_Optional_FK1.Name } + ? new MyInnerDto { Id = e.OneToOne_Optional_FK1.Id, Name = e.OneToOne_Optional_FK1.Name } : null - }).ToList().OrderBy(e => e.Id + " " + e.Name + " " + e.Inner).ToList(); - - Assert.Equal(expected.Count, actual.Count); - for (var i = 0; i < expected.Count; i++) + }), + elementSorter: e => e.Id, + elementAsserter: (e, a) => { - Assert.Equal(expected[i].Id, actual[i].Id); - Assert.Equal(expected[i].Name, actual[i].Name); - - if (expected[i].Inner == null) - { - Assert.Null(actual[i].Inner); - } - else - { - Assert.Equal(expected[i].Inner.Id, actual[i].Inner.Id); - Assert.Equal(expected[i].Inner.Name, actual[i].Inner.Name); - } - } - } + Assert.Equal(e.Id, a.Id); + Assert.Equal(e.Name, a.Name); + Assert.Equal(e.Inner?.Id, a.Inner?.Id); + Assert.Equal(e.Inner?.Name, a.Inner?.Name); + }); } public class MyOuterDto @@ -2814,27 +2795,37 @@ public virtual Task SelectMany_with_nested_required_navigation_filter_and_explic (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalFact] - public virtual void SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from l1 in ctx.LevelOne - join l2 in ctx.LevelFour.SelectMany( - l4 => l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2) on l1.Id - equals l2.Level1_Optional_Id - select new { l1, l2 }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - } + return AssertQuery( + isAsync, + ss => from l1 in ss.Set() + join l2 in ss.Set().SelectMany( + l4 => l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2) on l1.Id + equals l2.Level1_Optional_Id + select new { l1, l2 }, + ss => from l1 in ss.Set() + join l2 in ss.Set().SelectMany( + l4 => Maybe( + l4.OneToOne_Required_FK_Inverse4, + () => Maybe( + l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3, + () => l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2)) ?? new List()) on l1.Id + equals l2.Level1_Optional_Id + select new { l1, l2 }, + elementSorter: e => (e.l1.Id, e.l2.Id), + elementAsserter: (e, a) => + { + AssertEqual(e.l1, a.l1); + AssertEqual(e.l2, a.l2); + }); } [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany( - bool isAsync) + public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(bool isAsync) { return AssertQuery( isAsync, @@ -2867,8 +2858,7 @@ equals l2.Level1_Optional_Id [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2( - bool isAsync) + public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(bool isAsync) { return AssertQuery( isAsync, @@ -2897,8 +2887,7 @@ equals l2.Level1_Optional_Id [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3( - bool isAsync) + public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(bool isAsync) { return AssertQuery( isAsync, @@ -2924,8 +2913,7 @@ equals l2.Level1_Optional_Id [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4( - bool isAsync) + public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(bool isAsync) { return AssertQuery( isAsync, @@ -3030,8 +3018,7 @@ public virtual Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmp [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task - Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(bool isAsync) + public virtual Task Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(bool isAsync) { return AssertQuery( isAsync, @@ -4256,19 +4243,17 @@ orderby l3.Id select l3).Distinct().OrderBy(l => l.Id).Skip(1).FirstOrDefault().Name); } - [ConditionalFact(Skip = "issue #8523")] - public virtual void Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy() + [ConditionalTheory(Skip = "issue #8523")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from l1 in ctx.LevelOne - where l1.Id < 3 - select (from l3 in ctx.LevelThree - orderby l3.Id - select l3).Distinct().Skip(1).FirstOrDefault().Name; - - var result = query.ToList(); - } + return AssertQuery( + isAsync, + ss => from l1 in ss.Set() + where l1.Id < 3 + select (from l3 in ss.Set() + orderby l3.Id + select l3).Distinct().Skip(1).FirstOrDefault().Name); } [ConditionalTheory] @@ -4445,18 +4430,19 @@ select new }); } - [ConditionalFact] - public virtual void Include_inside_subquery() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_inside_subquery(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.LevelOne - .Where(l1 => l1.Id < 3) - .Select( - l1 => new { subquery = ctx.LevelTwo.Include(l => l.OneToMany_Optional2).Where(l => l.Id > 0).ToList() }); - - var result = query.ToList(); - } + // can't use AssertIncludeQuery here, see #18191 + return AssertQuery( + isAsync, + ss => ss.Set() + .Where(l1 => l1.Id <3) + .OrderBy(l1 => l1.Id) + .Select(l1 => new { subquery = ss.Set().Include(l => l.OneToMany_Optional2).Where(l => l.Id > 0).ToList() }), + assertOrder: true, + elementAsserter: (e, a) => AssertCollection(e.subquery, a.subquery)); } [ConditionalTheory] @@ -4960,18 +4946,24 @@ public virtual Task Multiple_SelectMany_navigation_property_followed_by_select_c }); } - [ConditionalFact] - public virtual void SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.LevelOne.SelectMany(l1 => l1.OneToMany_Optional1).Include(l2 => l2.OneToMany_Required2) - .Select(l2 => new { l2, l2.OneToMany_Optional2 }); - var result = query.ToList(); - - Assert.True(result.All(r => r.l2.OneToMany_Required2 != null)); - Assert.Contains(result, r => r.OneToMany_Optional2.Count > 0); - } + // can't use AssertIncludeQuery here, see #18191 + return AssertQuery( + isAsync, + ss => ss.Set() + .SelectMany(l1 => l1.OneToMany_Optional1) + .Include(l2 => l2.OneToMany_Required2) + .Select(l2 => new { l2, l2.OneToMany_Optional2 }), + elementSorter: e => e.l2.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.l2, a.l2); + AssertCollection(e.l2.OneToMany_Required2, a.l2.OneToMany_Required2); + AssertCollection(e.OneToMany_Optional2, a.OneToMany_Optional2); + }); } [ConditionalTheory] @@ -5517,27 +5509,40 @@ public virtual void IncludeCollection7() } } - [ConditionalFact] - public virtual void IncludeCollection8() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task IncludeCollection8(bool isAsync) { - using (var ctx = CreateContext()) + var expectedIncludes = new List { - var query = ctx.LevelOne.Include(l1 => l1.OneToMany_Optional1).ThenInclude(l2 => l2.OneToOne_Optional_PK2) - .ThenInclude(l3 => l3.OneToOne_Optional_FK3) - .Where(l1 => l1.OneToMany_Optional1.Where(l2 => l2.OneToOne_Optional_PK2.Name != "Foo").Count() > 0); + new ExpectedInclude(e => e.OneToMany_Optional1, "OneToMany_Optional1"), + new ExpectedInclude(e => e.OneToOne_Optional_PK2, "OneToOne_Optional_PK2", "OneToMany_Optional1"), + new ExpectedInclude(e => e.OneToOne_Optional_FK3, "OneToOne_Optional_FK3", "OneToMany_Optional1.OneToOne_Optional_PK2"), + }; - var result = query.ToList(); - } + return AssertIncludeQuery( + isAsync, + ss => ss.Set() + .Include(l1 => l1.OneToMany_Optional1) + .ThenInclude(l2 => l2.OneToOne_Optional_PK2) + .ThenInclude(l3 => l3.OneToOne_Optional_FK3) + .Where(l1 => l1.OneToMany_Optional1.Where(l2 => l2.OneToOne_Optional_PK2.Name != "Foo").Count() > 0), + ss => ss.Set() + .Include(l1 => l1.OneToMany_Optional1) + .ThenInclude(l2 => l2.OneToOne_Optional_PK2) + .ThenInclude(l3 => l3.OneToOne_Optional_FK3) + .Where(l1 => l1.OneToMany_Optional1.Where(l2 => Maybe(l2.OneToOne_Optional_PK2, () => l2.OneToOne_Optional_PK2.Name) != "Foo").Count() > 0), + expectedIncludes); } - [ConditionalFact] - public virtual void Include_with_all_method_include_gets_ignored() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_with_all_method_include_gets_ignored(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.LevelOne.Include(l1 => l1.OneToOne_Optional_FK1).Include(l1 => l1.OneToMany_Optional1) - .All(l1 => l1.Name != "Foo"); - } + return AssertAll( + isAsync, + ss => ss.Set().Include(l1 => l1.OneToOne_Optional_FK1).Include(l1 => l1.OneToMany_Optional1), + predicate: l1 => l1.Name != "Foo"); } [ConditionalTheory] @@ -5595,6 +5600,28 @@ orderby l4.Id } } + [ConditionalFact] + public virtual void Member_pushdown_chain_3_levels_deep_entity() + { + using (var ctx = CreateContext()) + { + var query = from l1 in ctx.LevelOne + orderby l1.Id + select (from l2 in ctx.LevelTwo + orderby l2.Id + where l2.Level1_Optional_Id == l1.Id + select (from l3 in ctx.LevelThree + orderby l3.Id + where l3.Level2_Required_Id == l2.Id + select (from l4 in ctx.LevelFour + where l4.Level3_Required_Id == l3.Id + orderby l4.Id + select l4).FirstOrDefault()).FirstOrDefault()).FirstOrDefault(); + + var result = query.ToList(); + } + } + [ConditionalFact] public virtual void Member_pushdown_with_collection_navigation_in_the_middle() { diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsWeakQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsWeakQueryTestBase.cs index 99f80522ce2..a360a1032d6 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsWeakQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsWeakQueryTestBase.cs @@ -81,31 +81,27 @@ public override Task Multiple_SelectMany_with_nested_navigations_and_explicit_De } [ConditionalTheory(Skip = "issue #13560")] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany( - bool isAsync) + public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(bool isAsync) { return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(isAsync); } [ConditionalTheory(Skip = "issue #13560")] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2( - bool isAsync) + public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(bool isAsync) { return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(isAsync); } - [ConditionalFact(Skip = "issue #13560")] - public override void SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany() + [ConditionalTheory(Skip = "issue #13560")] + public override Task SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(bool isAsync) { - base.SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(); + return base.SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(isAsync); } [ConditionalTheory(Skip = "issue #13560")] - public override Task - Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(bool isAsync) + public override Task Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(bool isAsync) { - return base.Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top( - isAsync); + return base.Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(isAsync); } [ConditionalTheory(Skip = "Issue#16752")] @@ -165,12 +161,18 @@ public override void Member_pushdown_chain_3_levels_deep() { } + public override void Member_pushdown_chain_3_levels_deep_entity() + { + } + public override void Member_pushdown_with_collection_navigation_in_the_middle() { } - public override void Include_inside_subquery() + [ConditionalTheory(Skip = "Issue#16752")] + public override Task Include_inside_subquery(bool isAsync) { + return base.Include_inside_subquery(isAsync); } } } diff --git a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs index d6ec94c6bde..a7c0716e1d3 100644 --- a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs @@ -82,15 +82,12 @@ public virtual Task ToString_guid_property_projection(bool isAsync) }); } - [ConditionalFact] - public virtual void Include_multiple_one_to_one_and_one_to_many_self_reference() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_multiple_one_to_one_and_one_to_many_self_reference(bool isAsync) { - using (var context = CreateContext()) - { - Assert.Throws( - () => context.Weapons.Include(w => w.Owner.Weapons).ToList()); - - } + return Assert.ThrowsAsync( + () => AssertQuery(isAsync, ss => ss.Set().Include(w => w.Owner.Weapons))); } [ConditionalTheory] @@ -110,14 +107,12 @@ public virtual Task Include_multiple_one_to_one_optional_and_one_to_one_required expectedIncludes); } - [ConditionalFact] - public virtual void Include_multiple_one_to_one_and_one_to_one_and_one_to_many() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_multiple_one_to_one_and_one_to_one_and_one_to_many(bool isAsync) { - using (var context = CreateContext()) - { - Assert.Throws( - () => context.Tags.Include(t => t.Gear.Squad.Members).ToList()); - } + return Assert.ThrowsAsync( + () => AssertQuery(isAsync, ss => ss.Set().Include(t => t.Gear.Squad.Members))); } [ConditionalTheory] @@ -170,18 +165,19 @@ public virtual Task Include_using_alternate_key(bool isAsync) expectedIncludes); } - [ConditionalFact] - public virtual void Include_multiple_include_then_include() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_multiple_include_then_include(bool isAsync) { - using (var context = CreateContext()) - { - Assert.Throws( - () => context.Gears.Include(g => g.AssignedCity.BornGears).ThenInclude(g => g.Tag) - .Include(g => g.AssignedCity.StationedGears).ThenInclude(g => g.Tag) - .Include(g => g.CityOfBirth.BornGears).ThenInclude(g => g.Tag) - .Include(g => g.CityOfBirth.StationedGears).ThenInclude(g => g.Tag) - .OrderBy(g => g.Nickname).ToList()); - } + return Assert.ThrowsAsync( + () => AssertQuery( + isAsync, + ss => ss.Set() + .Include(g => g.AssignedCity.BornGears).ThenInclude(g => g.Tag) + .Include(g => g.AssignedCity.StationedGears).ThenInclude(g => g.Tag) + .Include(g => g.CityOfBirth.BornGears).ThenInclude(g => g.Tag) + .Include(g => g.CityOfBirth.StationedGears).ThenInclude(g => g.Tag) + .OrderBy(g => g.Nickname))); } [ConditionalTheory] @@ -1373,29 +1369,26 @@ public virtual async Task Where_coalesce_with_anonymous_types(bool isAsync) RemoveNewLines(message)); } - [ConditionalFact(Skip = "issue #8421")] - public virtual void Where_compare_anonymous_types() + [ConditionalTheory(Skip = "issue #8421")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Where_compare_anonymous_types(bool isAsync) { - using (var context = CreateContext()) - { - var query = from g in context.Gears - from o in context.Gears.OfType() - where new - { - Name = g.LeaderNickname, - Squad = g.LeaderSquadId, - Five = 5 - } == new - { - Name = o.Nickname, - Squad = o.SquadId, - Five = 5 - } - select g.Nickname; - - var result = query.ToList(); - Assert.Equal(4, result.Count); - } + return AssertQuery( + isAsync, + ss => from g in ss.Set() + from o in ss.Set().OfType() + where new + { + Name = g.LeaderNickname, + Squad = g.LeaderSquadId, + Five = 5 + } == new + { + Name = o.Nickname, + Squad = o.SquadId, + Five = 5 + } + select g.Nickname); } [ConditionalTheory] @@ -1599,39 +1592,28 @@ public virtual Task Where_subquery_distinct_singleordefault_boolean_with_pushdow assertOrder: true); } - [ConditionalFact] - public virtual void Where_subquery_distinct_lastordefault_boolean() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Where_subquery_distinct_lastordefault_boolean(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Gears + return AssertQuery( + isAsync, + ss => ss.Set() .OrderBy(g => g.Nickname) - .Where(g => !g.Weapons.Distinct().OrderBy(w => w.Id).LastOrDefault().IsAutomatic); - - var result = query.ToList(); - - Assert.Equal(4, result.Count); - Assert.Equal("Baird", result[0].Nickname); - Assert.Equal("Dom", result[1].Nickname); - Assert.Equal("Marcus", result[2].Nickname); - Assert.Equal("Paduk", result[3].Nickname); - } + .Where(g => !g.Weapons.Distinct().OrderBy(w => w.Id).LastOrDefault().IsAutomatic), + assertOrder: true); } - [ConditionalFact] - public virtual void Where_subquery_distinct_last_boolean() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Where_subquery_distinct_last_boolean(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Gears + return AssertQuery( + isAsync, + ss => ss.Set() .OrderBy(g => g.Nickname) - .Where(g => !g.HasSoulPatch && g.Weapons.Distinct().OrderBy(w => w.Id).Last().IsAutomatic); - - var result = query.ToList(); - - Assert.Single(result); - Assert.Equal("Cole Train", result[0].Nickname); - } + .Where(g => !g.HasSoulPatch && g.Weapons.Distinct().OrderBy(w => w.Id).Last().IsAutomatic), + assertOrder: true); } [ConditionalTheory] @@ -1711,16 +1693,13 @@ public virtual Task Concat_anonymous_with_count(bool isAsync) }))); } - [ConditionalFact] - public virtual void Concat_with_scalar_projection() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Concat_with_scalar_projection(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Gears.Concat(context.Gears).Select(g => g.Nickname); - var result = query.ToList(); - - Assert.Equal(10, result.Count); - } + return AssertQuery( + isAsync, + ss => ss.Set().Concat(ss.Set()).Select(g => g.Nickname)); } [ConditionalTheory(Skip = "Issue #17068")] @@ -2860,26 +2839,24 @@ public virtual Task DateTimeOffset_DateAdd_AddMilliseconds(bool isAsync) select m.Timeline.AddMilliseconds(300)); } - [ConditionalFact] - public virtual void Where_datetimeoffset_milliseconds_parameter_and_constant() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Where_datetimeoffset_milliseconds_parameter_and_constant(bool isAsync) { - using (var ctx = CreateContext()) - { - var dateTimeOffset = new DateTimeOffset(599898024001234567, new TimeSpan(1, 30, 0)); - - // Parameter where clause - Assert.Equal(1, ctx.Missions.Where(m => m.Timeline == dateTimeOffset).Count()); + var dateTimeOffset = new DateTimeOffset(599898024001234567, new TimeSpan(1, 30, 0)); - // Literal where clause - var p = Expression.Parameter(typeof(Mission), "i"); - var dynamicWhere = Expression.Lambda>( - Expression.Equal( - Expression.Property(p, "Timeline"), - Expression.Constant(dateTimeOffset) - ), p); + // Literal where clause + var p = Expression.Parameter(typeof(Mission), "i"); + var dynamicWhere = Expression.Lambda>( + Expression.Equal( + Expression.Property(p, "Timeline"), + Expression.Constant(dateTimeOffset) + ), p); - Assert.Equal(1, ctx.Missions.Where(dynamicWhere).Count()); - } + return AssertCount( + isAsync, + ss => ss.Set().Where(dynamicWhere), + ss => ss.Set().Where(m => m.Timeline == dateTimeOffset)); } [ConditionalTheory(Skip = "Issue #17328")] @@ -3103,12 +3080,13 @@ public virtual Task Contains_with_local_nullable_guid_list_closure(bool isAsync) ss => ss.Set().Where(e => ids.Contains(e.Id))); } - [ConditionalFact] - public virtual void Unnecessary_include_doesnt_get_added_complex_when_projecting_EF_Property() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Unnecessary_include_doesnt_get_added_complex_when_projecting_EF_Property(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears + return AssertQuery( + isAsync, + ss => ss.Set() .OrderBy(g => g.Rank) .Include(g => g.Tag) .Where(g => g.HasSoulPatch) @@ -3116,103 +3094,81 @@ public virtual void Unnecessary_include_doesnt_get_added_complex_when_projecting g => new { FullName = EF.Property(g, "FullName") - }); - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Damon Baird", result[0].FullName); - Assert.Equal("Marcus Fenix", result[1].FullName); - } + }), + ss => ss.Set() + .OrderBy(g => g.Rank) + .Include(g => g.Tag) + .Where(g => g.HasSoulPatch) + .Select( + g => new + { + g.FullName + }), + assertOrder: true); } - [ConditionalFact] - public virtual void Multiple_order_bys_are_properly_lifted_from_subquery_created_by_include() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Multiple_order_bys_are_properly_lifted_from_subquery_created_by_include(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears + return AssertQuery( + isAsync, + ss => ss.Set() .OrderBy(g => g.Rank) .Include(g => g.Tag) .OrderByDescending(g => g.Nickname) .Include(g => g.CityOfBirth) .OrderBy(g => g.FullName) .Where(g => !g.HasSoulPatch) - .Select(g => g.FullName); - - var result = query.ToList(); - - Assert.Equal(3, result.Count); - Assert.Equal("Augustus Cole", result[0]); - Assert.Equal("Dominic Santiago", result[1]); - Assert.Equal("Garron Paduk", result[2]); - } + .Select(g => g.FullName), + assertOrder: true); } - [ConditionalFact] - public virtual void Order_by_is_properly_lifted_from_subquery_with_same_order_by_in_the_outer_query() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Order_by_is_properly_lifted_from_subquery_with_same_order_by_in_the_outer_query(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears - .OrderBy(g => g.FullName) + return AssertQuery( + isAsync, + ss => ss.Set() .Include(g => g.CityOfBirth) .OrderBy(g => g.FullName) .Where(g => !g.HasSoulPatch) - .Select(g => g.FullName); - - var result = query.ToList(); - - Assert.Equal(3, result.Count); - Assert.Equal("Augustus Cole", result[0]); - Assert.Equal("Dominic Santiago", result[1]); - Assert.Equal("Garron Paduk", result[2]); - } + .Select(g => g.FullName), + assertOrder: true); } - [ConditionalFact] - public virtual void Where_is_properly_lifted_from_subquery_created_by_include() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Where_is_properly_lifted_from_subquery_created_by_include(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears + return AssertIncludeQuery( + isAsync, + ss => ss.Set() .Where(g => g.FullName != "Augustus Cole") .Include(g => g.Tag) .OrderBy(g => g.FullName) .Where(g => !g.HasSoulPatch) - .Select(g => g); - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Dominic Santiago", result[0].FullName); - Assert.Equal("Dom's Tag", result[0].Tag.Note); - Assert.Equal("Garron Paduk", result[1].FullName); - Assert.Equal("Paduk's Tag", result[1].Tag.Note); - } + .Select(g => g), + expectedIncludes: new List { new ExpectedInclude(e => e.Tag, "Tag") }, + assertOrder: true); } - [ConditionalFact] - public virtual void Subquery_is_lifted_from_main_from_clause_of_SelectMany() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Subquery_is_lifted_from_main_from_clause_of_SelectMany(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from g1 in ctx.Gears.OrderBy(g => g.Rank).Include(g => g.Tag) - from g2 in ctx.Gears - orderby g1.FullName - where g1.HasSoulPatch && !g2.HasSoulPatch - select new - { - Name1 = g1.FullName, - Name2 = g2.FullName - }; - - var result = query.ToList(); - - Assert.Equal(6, result.Count); - Assert.True(result.All(r => r.Name1 == "Damon Baird" || r.Name1 == "Marcus Fenix")); - Assert.True(result.All(r => r.Name2 == "Augustus Cole" || r.Name2 == "Garron Paduk" || r.Name2 == "Dominic Santiago")); - } + return AssertQuery( + isAsync, + ss => from g1 in ss.Set().OrderBy(g => g.Rank).Include(g => g.Tag) + from g2 in ss.Set() + orderby g1.FullName + where g1.HasSoulPatch && !g2.HasSoulPatch + select new + { + Name1 = g1.FullName, + Name2 = g2.FullName + }); } [ConditionalTheory] @@ -3283,26 +3239,18 @@ orderby tag.Note assertOrder: true); } - [ConditionalFact] - public virtual void Subquery_created_by_include_gets_lifted_nested() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Subquery_created_by_include_gets_lifted_nested(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from gear in ctx.Gears.OrderBy(g => g.Rank).Where(g => g.Weapons.Any()).Include(g => g.CityOfBirth) - where !gear.HasSoulPatch - orderby gear.Nickname - select gear; - - var result = query.ToList(); - - Assert.Equal(3, result.Count); - Assert.Equal("Augustus Cole", result[0].FullName); - Assert.Equal("Hanover", result[0].CityOfBirth.Name); - Assert.Equal("Dominic Santiago", result[1].FullName); - Assert.Equal("Ephyra", result[1].CityOfBirth.Name); - Assert.Equal("Garron Paduk", result[2].FullName); - Assert.Equal("Unknown", result[2].CityOfBirth.Name); - } + return AssertIncludeQuery( + isAsync, + ss => from gear in ss.Set().OrderBy(g => g.Rank).Where(g => g.Weapons.Any()).Include(g => g.CityOfBirth) + where !gear.HasSoulPatch + orderby gear.Nickname + select gear, + expectedIncludes: new List { new ExpectedInclude(e => e.CityOfBirth, "CityOfBirth") }, + assertOrder: true); } [ConditionalTheory] @@ -3505,557 +3453,475 @@ private static IEnumerable Veterans(IEnumerable gears) return gears.Where(g => g.Nickname == "Marcus" || g.Nickname == "Dom" || g.Nickname == "Cole Train" || g.Nickname == "Baird"); } - [ConditionalFact] - public virtual void Member_access_on_derived_entity_using_cast() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Member_access_on_derived_entity_using_cast(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - orderby ((LocustHorde)f).Name - select new - { - ((LocustHorde)f).Name, - ((LocustHorde)f).Eradicated - }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.True(result[0].Eradicated); - Assert.Equal("Swarm", result[1].Name); - Assert.False(result[1].Eradicated); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + orderby ((LocustHorde)f).Name + select new + { + ((LocustHorde)f).Name, + ((LocustHorde)f).Eradicated + }, + assertOrder: true); } - [ConditionalFact] - public virtual void Member_access_on_derived_materialized_entity_using_cast() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Member_access_on_derived_materialized_entity_using_cast(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - orderby f.Name - select new - { - f, - ((LocustHorde)f).Eradicated - }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].f.Name); - Assert.True(result[0].Eradicated); - Assert.Equal("Swarm", result[1].f.Name); - Assert.False(result[1].Eradicated); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + orderby f.Name + select new + { + f, + ((LocustHorde)f).Eradicated + }, + assertOrder: true, + elementAsserter: (e, a) => + { + AssertEqual(e.f, a.f); + Assert.Equal(e.Eradicated, a.Eradicated); + }); } - [ConditionalFact] - public virtual void Member_access_on_derived_entity_using_cast_and_let() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Member_access_on_derived_entity_using_cast_and_let(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - let horde = (LocustHorde)f - orderby horde.Name - select new - { - horde.Name, - horde.Eradicated - }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.True(result[0].Eradicated); - Assert.Equal("Swarm", result[1].Name); - Assert.False(result[1].Eradicated); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + let horde = (LocustHorde)f + orderby horde.Name + select new + { + horde.Name, + horde.Eradicated + }, + assertOrder: true); } - [ConditionalFact] - public virtual void Property_access_on_derived_entity_using_cast() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Property_access_on_derived_entity_using_cast(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - let horde = (LocustHorde)f - orderby f.Name - select new - { - Name = EF.Property(horde, "Name"), - Eradicated = EF.Property((LocustHorde)f, "Eradicated") - }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.True(result[0].Eradicated); - Assert.Equal("Swarm", result[1].Name); - Assert.False(result[1].Eradicated); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + let horde = (LocustHorde)f + orderby f.Name + select new + { + Name = EF.Property(horde, "Name"), + Eradicated = EF.Property((LocustHorde)f, "Eradicated") + }, + ss => from f in ss.Set() + where f is LocustHorde + let horde = (LocustHorde)f + orderby f.Name + select new + { + horde.Name, + Eradicated = (bool)((LocustHorde)f).Eradicated + }, + assertOrder: true); } - [ConditionalFact] - public virtual void Navigation_access_on_derived_entity_using_cast() - { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - orderby f.Name - select new - { - f.Name, - Threat = ((LocustHorde)f).Commander.ThreatLevel - }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.Equal(5, result[0].Threat); - Assert.Equal("Swarm", result[1].Name); - Assert.Equal(0, result[1].Threat); - } - } - - [ConditionalFact] - public virtual void Navigation_access_on_derived_materialized_entity_using_cast() - { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - orderby f.Name - select new - { - f, - f.Name, - Threat = ((LocustHorde)f).Commander.ThreatLevel - }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.Equal("Locust", result[0].f.Name); - Assert.Equal(5, result[0].Threat); - Assert.Equal("Swarm", result[1].Name); - Assert.Equal("Swarm", result[1].f.Name); - Assert.Equal(0, result[1].Threat); - } - } - - [ConditionalFact] - public virtual void Navigation_access_via_EFProperty_on_derived_entity_using_cast() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Navigation_access_on_derived_entity_using_cast(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - orderby f.Name - select new - { - f.Name, - Threat = EF.Property((LocustHorde)f, "Commander").ThreatLevel - }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.Equal(5, result[0].Threat); - Assert.Equal("Swarm", result[1].Name); - Assert.Equal(0, result[1].Threat); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + orderby f.Name + select new + { + f.Name, + Threat = ((LocustHorde)f).Commander.ThreatLevel + }, + assertOrder: true); } - [ConditionalFact] - public virtual void Navigation_access_fk_on_derived_entity_using_cast() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Navigation_access_on_derived_materialized_entity_using_cast(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - orderby f.Name - select new - { - f.Name, - CommanderName = ((LocustHorde)f).Commander.Name - }; - - var result = query.ToList(); + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + orderby f.Name + select new + { + f, + f.Name, + Threat = ((LocustHorde)f).Commander.ThreatLevel + }, + assertOrder: true, + elementAsserter: (e, a) => + { + AssertEqual(e.f, a.f); + Assert.Equal(e.Name, a.Name); + Assert.Equal(e.Threat, a.Threat); - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.Equal("Queen Myrrah", result[0].CommanderName); - Assert.Equal("Swarm", result[1].Name); - Assert.Equal("Unknown", result[1].CommanderName); - } + }); } - [ConditionalFact] - public virtual void Collection_navigation_access_on_derived_entity_using_cast() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Navigation_access_via_EFProperty_on_derived_entity_using_cast(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - where f is LocustHorde - orderby f.Name - select new - { - f.Name, - LeadersCount = ((LocustHorde)f).Leaders.Count - }; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.Equal(4, result[0].LeadersCount); - Assert.Equal("Swarm", result[1].Name); - Assert.Equal(2, result[1].LeadersCount); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + orderby f.Name + select new + { + f.Name, + Threat = EF.Property((LocustHorde)f, "Commander").ThreatLevel + }, + ss => from f in ss.Set() + where f is LocustHorde + orderby f.Name + select new + { + f.Name, + Threat = ((LocustHorde)f).Commander.ThreatLevel + }, + assertOrder: true); } - [ConditionalFact] - public virtual void Collection_navigation_access_on_derived_entity_using_cast_in_SelectMany() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Navigation_access_fk_on_derived_entity_using_cast(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions.Where(f => f is LocustHorde) - from l in ((LocustHorde)f).Leaders - orderby l.Name - select new - { - f.Name, - LeaderName = l.Name - }; - - var result = query.ToList(); - - Assert.Equal(6, result.Count); - Assert.Equal("Locust", result[0].Name); - Assert.Equal("Locust", result[1].Name); - Assert.Equal("Locust", result[2].Name); - Assert.Equal("Locust", result[3].Name); - Assert.Equal("Swarm", result[4].Name); - Assert.Equal("General Karn", result[0].LeaderName); - Assert.Equal("General RAAM", result[1].LeaderName); - Assert.Equal("High Priest Skorge", result[2].LeaderName); - Assert.Equal("Queen Myrrah", result[3].LeaderName); - Assert.Equal("The Speaker", result[4].LeaderName); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + orderby f.Name + select new + { + f.Name, + CommanderName = ((LocustHorde)f).Commander.Name + }, + assertOrder: true); } - [ConditionalFact] - public virtual void Include_on_derived_entity_using_OfType() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Collection_navigation_access_on_derived_entity_using_cast(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from lh in ctx.Factions.OfType().Include(h => h.Commander).Include(h => h.Leaders) - orderby lh.Name - select lh; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Queen Myrrah", result[0].Commander.Name); - Assert.Equal(4, result[0].Leaders.Count); - Assert.Equal("Unknown", result[1].Commander.Name); - Assert.Equal(2, result[1].Leaders.Count); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + where f is LocustHorde + orderby f.Name + select new + { + f.Name, + LeadersCount = ((LocustHorde)f).Leaders.Count + }, + assertOrder: true); } - [ConditionalFact(Skip = "Issue#16089")] - public virtual void Include_on_derived_entity_using_subquery_with_cast() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Collection_navigation_access_on_derived_entity_using_cast_in_SelectMany(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from lh in (from f in ctx.Factions - where f is LocustHorde - select (LocustHorde)f).Include(h => h.Commander).Include(h => h.Leaders) - orderby lh.Name - select lh; - - var result = query.ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal("Queen Myrrah", result[0].Commander.Name); - Assert.Equal(4, result[0].Leaders.Count); - Assert.Equal("Unknown", result[1].Commander.Name); - Assert.Equal(2, result[1].Leaders.Count); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set().Where(f => f is LocustHorde) + from l in ((LocustHorde)f).Leaders + orderby l.Name + select new + { + f.Name, + LeaderName = l.Name + }, + elementSorter: e => (e.Name, e.LeaderName)); } - [ConditionalFact(Skip = "Issue#16089")] - public virtual void Include_on_derived_entity_using_subquery_with_cast_AsNoTracking() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_on_derived_entity_using_OfType(bool isAsync) { - using (var ctx = CreateContext()) + var expectedIncludes = new List { - var query = from lh in (from f in ctx.Factions - where f is LocustHorde - select (LocustHorde)f).AsNoTracking().Include(h => h.Commander).Include(h => h.Leaders) - orderby lh.Name - select lh; - - var result = query.ToList(); + new ExpectedInclude(e => e.Commander, "Commander"), + new ExpectedInclude(e => e.Leaders, "Leaders") + }; - Assert.Equal(2, result.Count); - Assert.Equal("Queen Myrrah", result[0].Commander.Name); - Assert.Equal(4, result[0].Leaders.Count); - Assert.Equal("Unknown", result[1].Commander.Name); - Assert.Equal(2, result[1].Leaders.Count); - } + return AssertIncludeQuery( + isAsync, + ss => from lh in ss.Set().OfType().Include(h => h.Commander).Include(h => h.Leaders) + orderby lh.Name + select lh, + expectedIncludes, + assertOrder: true); } - [ConditionalFact(Skip = "Issue#16089")] - public virtual void Include_on_derived_entity_using_subquery_with_cast_cross_product_base_entity() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_on_derived_entity_with_cast(bool isAsync) { - using (var ctx = CreateContext()) + var expectedIncludes = new List { - var query = from lh in (from f2 in ctx.Factions - where f2 is LocustHorde - select (LocustHorde)f2).Include(h => h.Commander).Include(h => h.Leaders) - from f in ctx.Factions.Include(ff => ff.Capital) - orderby lh.Name, f.Name - select new - { - lh, - f - }; - - var result = query.ToList(); + new ExpectedInclude(e => e.Capital, "Capital"), + }; - Assert.Equal(4, result.Count); - Assert.Equal("Queen Myrrah", result[0].lh.Commander.Name); - Assert.Equal(4, result[0].lh.Leaders.Count); - Assert.Equal("Unknown", result[2].lh.Commander.Name); - Assert.Equal(2, result[2].lh.Leaders.Count); - } + // TODO: should we disable this scenario? see #14671 + return AssertIncludeQuery( + isAsync, + ss => (from f in ss.Set() + where f is LocustHorde + select f).Include(f => f.Capital), + expectedIncludes, + assertOrder: true); } - [ConditionalFact] - public virtual void Distinct_on_subquery_doesnt_get_lifted() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Distinct_on_subquery_doesnt_get_lifted(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from g in (from ig in ctx.Gears - select ig).Distinct() - select g.HasSoulPatch; - - var result = query.ToList(); - Assert.Equal(5, result.Count); - } + return AssertQueryScalar( + isAsync, + ss => from g in (from ig in ss.Set() + select ig).Distinct() + select g.HasSoulPatch); } - [ConditionalFact] - public virtual void Cast_result_operator_on_subquery_is_properly_lifted_to_a_convert() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Cast_result_operator_on_subquery_is_properly_lifted_to_a_convert(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from lh in (from f in ctx.Factions - select f).Cast() - select lh.Eradicated; - - var result = query.ToList(); - Assert.Equal(2, result.Count); - } + return AssertQueryScalar( + isAsync, + ss => from lh in (from f in ss.Set() + select f).Cast() + select lh.Eradicated); } - [ConditionalFact] - public virtual void Comparing_two_collection_navigations_composite_key() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Comparing_two_collection_navigations_composite_key(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from g1 in ctx.Gears - from g2 in ctx.Gears - // ReSharper disable once PossibleUnintendedReferenceComparison - where g1.Weapons == g2.Weapons - orderby g1.Nickname - select new - { - Nickname1 = g1.Nickname, - Nickname2 = g2.Nickname - }; - - var result = query.ToList(); - Assert.Equal(5, result.Count); - Assert.Equal(5, result.Count(r => r.Nickname1 == r.Nickname2)); - } + return AssertQuery( + isAsync, + ss => from g1 in ss.Set() + from g2 in ss.Set() + // ReSharper disable once PossibleUnintendedReferenceComparison + where g1.Weapons == g2.Weapons + orderby g1.Nickname + select new + { + Nickname1 = g1.Nickname, + Nickname2 = g2.Nickname + }, + elementSorter: e => (e.Nickname1, e.Nickname2)); } - [ConditionalFact] - public virtual void Comparing_two_collection_navigations_inheritance() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Comparing_two_collection_navigations_inheritance(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from f in ctx.Factions - from o in ctx.Gears.OfType() - where f is LocustHorde && o.HasSoulPatch - // ReSharper disable once PossibleUnintendedReferenceComparison - where ((LocustHorde)f).Commander.DefeatedBy.Weapons == o.Weapons - select new - { - f.Name, - o.Nickname - }; - - var result = query.ToList(); - Assert.Single(result); - Assert.Equal("Locust", result[0].Name); - Assert.Equal("Marcus", result[0].Nickname); - } + return AssertQuery( + isAsync, + ss => from f in ss.Set() + from o in ss.Set().OfType() + where f is LocustHorde && o.HasSoulPatch + // ReSharper disable once PossibleUnintendedReferenceComparison + where ((LocustHorde)f).Commander.DefeatedBy.Weapons == o.Weapons + select new + { + f.Name, + o.Nickname + }, + ss => from f in ss.Set() + from o in ss.Set().OfType() + where f is LocustHorde && o.HasSoulPatch + where Maybe( + ((LocustHorde)f).Commander, + () => ((LocustHorde)f).Commander.DefeatedBy) == o + select new + { + f.Name, + o.Nickname + }, + elementSorter: e => (e.Name, e.Nickname)); } - [ConditionalFact] - public virtual void Comparing_entities_using_Equals_inheritance() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Comparing_entities_using_Equals_inheritance(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = from g in ctx.Gears - from o in ctx.Gears.OfType() - where g.Equals(o) - orderby g.Nickname - select new - { - Nickname1 = g.Nickname, - Nickname2 = o.Nickname - }; - - var result = query.ToList(); - Assert.Equal(2, result.Count); - Assert.Equal("Baird", result[0].Nickname1); - Assert.Equal("Baird", result[0].Nickname2); - Assert.Equal("Marcus", result[1].Nickname1); - Assert.Equal("Marcus", result[1].Nickname2); - } + return AssertQuery(isAsync, + ss => from g in ss.Set() + from o in ss.Set().OfType() + where g.Equals(o) + orderby g.Nickname, o.Nickname + select new + { + Nickname1 = g.Nickname, + Nickname2 = o.Nickname + }, + assertOrder: true); } - [ConditionalFact] - public virtual void Contains_on_nullable_array_produces_correct_sql() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Contains_on_nullable_array_produces_correct_sql(bool isAsync) { - using (var context = CreateContext()) - { - var cities = new[] { "Ephyra", null }; - var query = context.Gears.Where(g => g.SquadId < 2 && cities.Contains(g.AssignedCity.Name)).ToList(); + var cities = new[] { "Ephyra", null }; - Assert.Equal(2, query.Count); - } + return AssertQuery( + isAsync, + ss => ss.Set().Where(g => g.SquadId < 2 && cities.Contains(g.AssignedCity.Name)), + ss => ss.Set().Where(g => g.SquadId < 2 && cities.Contains(Maybe(g.AssignedCity, () => g.AssignedCity.Name)))); } - [ConditionalFact] - public virtual void Optional_navigation_with_collection_composite_key() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Optional_navigation_with_collection_composite_key(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Tags.Where(t => t.Gear is Officer && ((Officer)t.Gear).Reports.Count(r => r.Nickname == "Dom") > 0); - var result = query.ToList(); - - Assert.Single(result); - Assert.Equal("Marcus' Tag", result[0].Note); - } + return AssertQuery( + isAsync, + ss => ss.Set().Where(t => t.Gear is Officer && ((Officer)t.Gear).Reports.Count(r => r.Nickname == "Dom") > 0)); } - [ConditionalFact] - public virtual void Select_null_conditional_with_inheritance() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Select_null_conditional_with_inheritance(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Factions + return AssertQuery( + isAsync, + ss => ss.Set() .Where(f => f is LocustHorde) - .Select(f => EF.Property((LocustHorde)f, "CommanderName") != null ? ((LocustHorde)f).CommanderName : null); - - var result = query.ToList(); - Assert.Equal(2, result.Count); - Assert.Contains("Queen Myrrah", result); - Assert.Contains("Unknown", result); - } + .Select(f => EF.Property((LocustHorde)f, "CommanderName") != null ? ((LocustHorde)f).CommanderName : null), + ss => ss.Set() + .Where(f => f is LocustHorde) + .Select(f => ((LocustHorde)f).CommanderName != null ? ((LocustHorde)f).CommanderName : null)); } - [ConditionalFact] - public virtual void Select_null_conditional_with_inheritance_negative() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Select_null_conditional_with_inheritance_negative(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Factions + return AssertQueryScalar( + isAsync, + ss => ss.Set() .Where(f => f is LocustHorde) - .Select(f => EF.Property((LocustHorde)f, "CommanderName") != null ? ((LocustHorde)f).Eradicated : null); - - var result = query.ToList(); - Assert.Equal(2, result.Count); - Assert.Contains(true, result); - Assert.Contains(false, result); - } + .Select(f => EF.Property((LocustHorde)f, "CommanderName") != null ? ((LocustHorde)f).Eradicated : null), + ss => ss.Set() + .Where(f => f is LocustHorde) + .Select(f => ((LocustHorde)f).CommanderName != null ? ((LocustHorde)f).Eradicated : null)); } - [ConditionalFact] - public virtual void Project_collection_navigation_with_inheritance1() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_collection_navigation_with_inheritance1(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Factions.OfType() + return AssertQuery( + isAsync, + ss => ss.Set().OfType() .Select( h => new { h.Id, Leaders = EF.Property>(h.Commander.CommandingFaction, "Leaders") - }); - - var result = query.ToList(); - Assert.Equal(2, result.Count); - Assert.Equal(1, result.Count(r => r.Id == 1 && r.Leaders.Count == 4)); - Assert.Equal(1, result.Count(r => r.Id == 2 && r.Leaders.Count == 2)); - } + }), + ss => ss.Set().OfType() + .Select( + h => new + { + h.Id, + Leaders = (ICollection)h.Commander.CommandingFaction.Leaders + }), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + Assert.Equal(e.Id, a.Id); + AssertCollection(e.Leaders, a.Leaders); + }); } - [ConditionalFact] - public virtual void Project_collection_navigation_with_inheritance2() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_collection_navigation_with_inheritance2(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Factions.OfType() + return AssertQuery( + isAsync, + ss => ss.Set().OfType() .Select( h => new { h.Id, Gears = EF.Property>((Officer)h.Commander.DefeatedBy, "Reports") - }); - - var result = query.ToList(); - Assert.Equal(2, result.Count); - Assert.Equal(1, result.Count(r => r.Id == 1 && r.Gears.Count == 3)); - Assert.Equal(1, result.Count(r => r.Id == 2 && r.Gears.Count == 0)); - } + }), + ss => ss.Set().OfType() + .Select( + h => new + { + h.Id, + Gears = Maybe( + h.Commander, + () => Maybe( + h.Commander.DefeatedBy, + () => ((Officer)h.Commander.DefeatedBy).Reports)) ?? new List() + }), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + Assert.Equal(e.Id, a.Id); + AssertCollection(e.Gears, a.Gears); + }); } - [ConditionalFact] - public virtual void Project_collection_navigation_with_inheritance3() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_collection_navigation_with_inheritance3(bool isAsync) { - using (var context = CreateContext()) - { - var query = context.Factions + return AssertQuery( + isAsync, + ss => ss.Set() .Where(f => f is LocustHorde) .Select( f => new { f.Id, Gears = EF.Property>((Officer)((LocustHorde)f).Commander.DefeatedBy, "Reports") - }); - - var result = query.ToList(); - Assert.Equal(2, result.Count); - Assert.Equal(1, result.Count(r => r.Id == 1 && r.Gears.Count == 3)); - Assert.Equal(1, result.Count(r => r.Id == 2 && r.Gears.Count == 0)); - } + }), + ss => ss.Set() + .Where(f => f is LocustHorde) + .Select( + f => new + { + f.Id, + Gears = Maybe( + ((LocustHorde)f).Commander, + () => Maybe( + ((LocustHorde)f).Commander.DefeatedBy, + () => ((Officer)((LocustHorde)f).Commander.DefeatedBy).Reports)) ?? new List() + }), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + Assert.Equal(e.Id, a.Id); + AssertCollection(e.Gears, a.Gears); + }); } [ConditionalTheory] @@ -4298,21 +4164,18 @@ public virtual Task Include_on_derived_multi_level(bool isAsync) expectedIncludes); } - [ConditionalFact(Skip = "Issue#15312")] - public virtual void Include_collection_and_invalid_navigation_using_string_throws() - { + [ConditionalTheory(Skip = "Issue#15312")] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Include_collection_and_invalid_navigation_using_string_throws(bool isAsync) + { + var message = (await Assert.ThrowsAsync( + () => AssertQuery( + isAsync, + ss => ss.Set().Include("Reports.Foo")))).Message; + Assert.Equal( CoreStrings.IncludeBadNavigation("Foo", "Gear"), - Assert.Throws( - () => - { - using (var context = CreateContext()) - { - var query = context.Gears - .Include("Reports.Foo") - .ToList(); - } - }).Message); + message); } [ConditionalTheory] @@ -5486,24 +5349,14 @@ select new }); } - [ConditionalFact] - public virtual void Correlated_collection_with_top_level_FirstOrDefault() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Correlated_collection_with_top_level_FirstOrDefault(bool isAsync) { - using (var ctx = CreateContext()) - { - var actual = ctx.Gears.OrderBy(g => g.Nickname).Select(g => g.Weapons).FirstOrDefault(); - var expected = Fixture.QueryAsserter.ExpectedData.Set().OrderBy(g => g.Nickname).Select(g => g.Weapons).FirstOrDefault(); - - Assert.Equal(expected.Count, actual.Count); - - var actualList = actual.ToList(); - var expectedList = expected.ToList(); - for (var i = 0; i < expected.Count; i++) - { - Assert.Equal(expectedList[i].Id, actualList[i].Id); - Assert.Equal(expectedList[i].Name, actualList[i].Name); - } - } + return AssertFirstOrDefault( + isAsync, + ss => ss.Set().OrderBy(g => g.Nickname).Select(g => g.Weapons), + asserter: (e, a) => AssertCollection(e, a)); } [ConditionalTheory] @@ -5515,46 +5368,24 @@ public virtual Task Correlated_collection_with_top_level_Count(bool isAsync) ss => ss.Set().Select(g => g.Weapons)); } - [ConditionalFact] - public virtual void Correlated_collection_with_top_level_Last_with_orderby_on_outer() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Correlated_collection_with_top_level_Last_with_orderby_on_outer(bool isAsync) { - using (var ctx = CreateContext()) - { - var actual = ctx.Gears.OrderByDescending(g => g.FullName).Select(g => g.Weapons).Last(); - var expected = Fixture.QueryAsserter.ExpectedData.Set().OrderByDescending(g => g.FullName).Select(g => g.Weapons) - .Last(); - - Assert.Equal(expected.Count, actual.Count); - - var actualList = actual.ToList(); - var expectedList = expected.ToList(); - for (var i = 0; i < expected.Count; i++) - { - Assert.Equal(expectedList[i].Id, actualList[i].Id); - Assert.Equal(expectedList[i].Name, actualList[i].Name); - } - } + return AssertLast( + isAsync, + ss => ss.Set().OrderByDescending(g => g.FullName).Select(g => g.Weapons), + asserter: (e, a) => AssertCollection(e, a)); } - [ConditionalFact] - public virtual void Correlated_collection_with_top_level_Last_with_order_by_on_inner() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Correlated_collection_with_top_level_Last_with_order_by_on_inner(bool isAsync) { - using (var ctx = CreateContext()) - { - var actual = ctx.Gears.OrderBy(g => g.FullName).Select(g => g.Weapons.OrderBy(w => w.Name).ToList()).Last(); - var expected = Fixture.QueryAsserter.ExpectedData.Set().OrderBy(g => g.FullName) - .Select(g => g.Weapons.OrderBy(w => w.Name).ToList()).Last(); - - Assert.Equal(expected.Count, actual.Count); - - var actualList = actual.ToList(); - var expectedList = expected.ToList(); - for (var i = 0; i < expected.Count; i++) - { - Assert.Equal(expectedList[i].Id, actualList[i].Id); - Assert.Equal(expectedList[i].Name, actualList[i].Name); - } - } + return AssertLast( + isAsync, + ss => ss.Set().OrderBy(g => g.FullName).Select(g => g.Weapons.OrderBy(w => w.Name).ToList()), + asserter: (e, a) => AssertCollection(e, a, ordered: true)); } [ConditionalFact(Skip = "Issue #17068")] @@ -6199,41 +6030,16 @@ public virtual void Include_with_group_by_on_entity_navigation_with_inheritance( } } - [ConditionalFact(Skip = "Issue#16314")] - public virtual void Streaming_correlated_collection_issue_11403() + [ConditionalTheory(Skip = "Issue#16314")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Streaming_correlated_collection_issue_11403(bool isAsync) { - Weapon[] expected; - using (var context = CreateContext()) - { - expected = context.Gears.OrderBy(g => g.Nickname) - .Select(g => g.Weapons.Where(w => !w.IsAutomatic).OrderBy(w => w.Id).ToArray()) - .FirstOrDefault(); - - ClearLog(); - } - - using (var context = CreateContext()) - { - var query = context.Gears + return AssertFirstOrDefault( + isAsync, + ss => ss.Set() .OrderBy(g => g.Nickname) - .Select(g => g.Weapons.Where(w => !w.IsAutomatic).OrderBy(w => w.Id)) - .FirstOrDefault() - .ToArray(); - - Assert.Equal(expected.Length, query.Length); - - for (var i = 0; i < expected.Length; i++) - { - Assert.Equal(expected[i].Id, query[i].Id); - Assert.Equal(expected[i].AmmunitionType, query[i].AmmunitionType); - Assert.Equal(expected[i].IsAutomatic, query[i].IsAutomatic); - Assert.Equal(expected[i].Name, query[i].Name); - Assert.Equal(expected[i].Owner, query[i].Owner); - Assert.Equal(expected[i].OwnerFullName, query[i].OwnerFullName); - Assert.Equal(expected[i].SynergyWith, query[i].SynergyWith); - Assert.Equal(expected[i].SynergyWithId, query[i].SynergyWithId); - } - } + .Select(g => g.Weapons.Where(w => !w.IsAutomatic).OrderBy(w => w.Id)), + asserter: (e, a) => AssertCollection(e, a, ordered: true)); } [ConditionalTheory] @@ -6580,14 +6386,11 @@ public virtual Task Correlated_collection_with_very_complex_order_by(bool isAsyn elementAsserter: (e, a) => AssertCollection(e, a)); } - [ConditionalFact] - public virtual void Cast_to_derived_type_causes_client_eval() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Cast_to_derived_type_causes_client_eval(bool isAsync) { - using (var context = CreateContext()) - { - Assert.Throws( - () => context.Gears.Cast().ToList()); - } + return Assert.ThrowsAsync(() => AssertQuery(isAsync, ss => ss.Set().Cast())); } [ConditionalTheory] @@ -7113,27 +6916,24 @@ public virtual Task Include_collection_with_Cast_to_base(bool isAsync) new List { new ExpectedInclude(e => e.Weapons, "Weapons") }); } - [ConditionalFact] - public virtual void Include_with_client_method_and_member_access_still_applies_includes() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_with_client_method_and_member_access_still_applies_includes(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears + return AssertQuery( + isAsync, + ss => ss.Set() .Include(g => g.Tag) - .Select(g => new { g.Nickname, Client(g).FullName }); - - var result = query.ToList(); - } + .Select(g => new { g.Nickname, Client(g).FullName })); } - [ConditionalFact] - public virtual void Include_with_projection_of_unmapped_property_still_gets_applied() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_with_projection_of_unmapped_property_still_gets_applied(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears.Include(g => g.Weapons).Select(g => g.IsMarcus); - var result = query.ToList(); - } + return AssertQueryScalar( + isAsync, + ss => ss.Set().Include(g => g.Weapons).Select(g => g.IsMarcus)); } [ConditionalFact] @@ -7344,34 +7144,43 @@ public virtual async Task Filter_with_new_Guid_closure(bool isAsync) select t); } - [ConditionalFact] - public virtual void OfTypeNav1() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task OfTypeNav1(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears.Where(g => g.Tag.Note != "Foo").OfType().Where(o => o.Tag.Note != "Bar"); - var result = query.ToList(); - } + return AssertQuery( + isAsync, + ss => ss.Set().Where(g => g.Tag.Note != "Foo").OfType().Where(o => o.Tag.Note != "Bar")); } - [ConditionalFact] - public virtual void OfTypeNav2() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task OfTypeNav2(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears.Where(g => g.Tag.Note != "Foo").OfType().Where(o => o.AssignedCity.Location != "Bar"); - var result = query.ToList(); - } + return AssertQuery( + isAsync, + ss => ss.Set().Where(g => g.Tag.Note != "Foo").OfType().Where(o => o.AssignedCity.Location != "Bar"), + ss => ss.Set() + .Where(g => Maybe(g.Tag, () => g.Tag.Note) != "Foo") + .OfType() + .Where(o => Maybe(o.AssignedCity, () => o.AssignedCity.Location) != "Bar")); } - [ConditionalFact] - public virtual void OfTypeNav3() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task OfTypeNav3(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears.Where(g => g.Tag.Note != "Foo").Join(ctx.Weapons, g => g.FullName, w => w.OwnerFullName, (o, i) => o).OfType().Where(o => o.Tag.Note != "Bar"); - var result = query.ToList(); - } + return AssertQuery( + isAsync, + ss => ss.Set() + .Where(g => g.Tag.Note != "Foo") + .Join( + ss.Set(), + g => g.FullName, + w => w.OwnerFullName, + (o, i) => o) + .OfType() + .Where(o => o.Tag.Note != "Bar")); } [ConditionalFact(Skip = "Issue #17328")] @@ -7396,34 +7205,36 @@ public virtual void Nav_rewrite_Distinct_with_convert_anonymous() } } - [ConditionalFact] - public virtual void Nav_rewrite_with_convert1() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Nav_rewrite_with_convert1(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Factions.Where(f => f.Capital.Name != "Foo").Select(f => ((LocustHorde)f).Commander); - var result = query.ToList(); - } + return AssertQuery( + isAsync, + ss => ss.Set().Where(f => f.Capital.Name != "Foo").Select(f => ((LocustHorde)f).Commander), + ss => ss.Set().Where(f => Maybe(f.Capital, () => f.Capital.Name) != "Foo").Select(f => ((LocustHorde)f).Commander)); } - [ConditionalFact] - public virtual void Nav_rewrite_with_convert2() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Nav_rewrite_with_convert2(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Factions.Where(f => f.Capital.Name != "Foo").Select(f => (LocustHorde)f).Where(lh => lh.Commander.Name != "Bar"); - var result = query.ToList(); - } + return AssertQuery( + isAsync, + ss => ss.Set().Where(f => f.Capital.Name != "Foo").Select(f => (LocustHorde)f).Where(lh => lh.Commander.Name != "Bar"), + ss => ss.Set().Where(f => Maybe(f.Capital, () => f.Capital.Name) != "Foo").Select(f => (LocustHorde)f).Where(lh => lh.Commander.Name != "Bar")); } - [ConditionalFact] - public virtual void Nav_rewrite_with_convert3() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Nav_rewrite_with_convert3(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Factions.Where(f => f.Capital.Name != "Foo").Select(f => new { horde = (LocustHorde)f }).Where(x => x.horde.Commander.Name != "Bar"); - var result = query.ToList(); - } + return AssertQuery( + isAsync, + ss => ss.Set().Where(f => f.Capital.Name != "Foo").Select(f => new { horde = (LocustHorde)f }).Where(x => x.horde.Commander.Name != "Bar"), + ss => ss.Set().Where(f => Maybe(f.Capital, () => f.Capital.Name) != "Foo").Select(f => new { horde = (LocustHorde)f }).Where(x => x.horde.Commander.Name != "Bar"), + elementSorter: e => e.horde.Id, + elementAsserter: (e, a) => AssertEqual(e.horde, a.horde)); } [ConditionalTheory(Skip = "Issue#15260")] @@ -7435,24 +7246,33 @@ public virtual Task Where_contains_on_navigation_with_composite_keys(bool isAsyn ss => ss.Set().Where(g => ss.Set().Any(c => c.BornGears.Contains(g)))); } - [ConditionalFact] - public virtual void Project_derivied_entity_with_convert_to_parent() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_derivied_entity_with_convert_to_parent(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Factions.OfType().Select(f => (Faction)f); - var result = query.ToList(); - } + return AssertQuery( + isAsync, + ss => ss.Set().OfType().Select(f => (Faction)f)); } - [ConditionalFact] - public virtual void Include_with_complex_order_by() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Include_with_complex_order_by(bool isAsync) { - using (var ctx = CreateContext()) - { - var query = ctx.Gears.Include(g => g.Weapons).OrderBy(g => g.Weapons.FirstOrDefault(w => w.Name.Contains("Gnasher")).Name).ThenBy(g => g.Nickname); - var result = query.ToList(); - } + return AssertIncludeQuery( + isAsync, + ss => ss.Set() + .Include(g => g.Weapons) + .OrderBy(g => g.Weapons.FirstOrDefault(w => w.Name.Contains("Gnasher")).Name) + .ThenBy(g => g.Nickname), + ss => ss.Set() + .Include(g => g.Weapons) + .OrderBy(g => Maybe( + g.Weapons.FirstOrDefault(w => w.Name.Contains("Gnasher")), + () => g.Weapons.FirstOrDefault(w => w.Name.Contains("Gnasher")).Name)) + .ThenBy(g => g.Nickname), + expectedIncludes: new List { new ExpectedInclude(e => e.Weapons, "Weapons") }, + assertOrder: true); } [ConditionalTheory(Skip = "issue #12603")] @@ -7791,6 +7611,148 @@ public virtual Task Collection_navigation_ofType_filter_works(bool isAsync) ss => ss.Set().Where(c => c.BornGears.OfType().Any(o => o.Nickname == "Marcus"))); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Include_after_select_with_cast_throws(bool isAsync) + { + Assert.Equal( + "Include has been used on non entity queryable.", + (await Assert.ThrowsAsync( + () => AssertQuery( + isAsync, + ss => ss.Set().Where(f => f is LocustHorde).Select(f => (LocustHorde)f).Include(h => h.Commander)))).Message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Include_after_select_with_entity_projection_throws(bool isAsync) + { + Assert.Equal( + "Include has been used on non entity queryable.", + (await Assert.ThrowsAsync( + () => AssertQuery( + isAsync, + ss => ss.Set().Select(f => f.Capital).Include(c => c.BornGears)))).Message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Include_after_select_anonymous_projection_throws(bool isAsync) + { + Assert.Equal( + "Include has been used on non entity queryable.", + (await Assert.ThrowsAsync( + () => AssertQuery( + isAsync, + ss => ss.Set().Select(f => new { f }).Include(x => x.f.Capital)))).Message); + } + + [ConditionalTheory(Skip = "issue #14671")] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Include_after_Select_throws(bool isAsync) + { + Assert.Equal( + "Include has been used on non entity queryable.", + (await Assert.ThrowsAsync( + () => AssertQuery( + isAsync, + ss => ss.Set().Select(f => f).Include(h => h.Capital)))).Message); + } + + [ConditionalTheory(Skip = "issue #14671")] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Include_after_SelectMany_throws(bool isAsync) + { + Assert.Equal( + "Include has been used on non entity queryable.", + (await Assert.ThrowsAsync( + () => AssertQuery( + isAsync, + ss => ss.Set().SelectMany(f => f.Capital.BornGears).Include(g => g.Squad), + ss => ss.Set().SelectMany(f => Maybe(f.Capital, () => f.Capital.BornGears) ?? new List())))).Message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Query_reusing_parameter_doesnt_declare_duplicate_parameter(bool isAsync) + { + var prm = new ComplexParameter + { + Inner = new ComplexParameterInner + { + Nickname = "Marcus", + } + }; + + return AssertQuery( + isAsync, + ss => ss.Set() + .Where(g => g.Nickname != prm.Inner.Nickname) + .Distinct() + .Where(g => g.Nickname != prm.Inner.Nickname) + .OrderBy(g => g.FullName), + assertOrder: true); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Query_reusing_parameter_doesnt_declare_duplicate_parameter_complex(bool isAsync) + { + var prm = new ComplexParameter + { + Inner = new ComplexParameterInner + { + Squad = new Squad { Id = 1 } + } + }; + + return AssertQuery( + isAsync, + ss => ss.Set() + .Where(g => g.Squad == prm.Inner.Squad) + .Distinct() + .Where(g => g.Squad == prm.Inner.Squad) + .OrderBy(g => g.FullName), + ss => ss.Set() + .Where(g => g.Squad.Id == prm.Inner.Squad.Id) + .Distinct() + .Where(g => g.Squad.Id == prm.Inner.Squad.Id) + .OrderBy(g => g.FullName), + assertOrder: true); + } + + private class ComplexParameter + { + public ComplexParameterInner Inner { get; set; } + } + + private class ComplexParameterInner + { + public string Nickname { get; set; } + public Squad Squad { get; set; } + } + + [ConditionalTheory(Skip = "issue #17852")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_entity_and_collection_element(bool isAsync) + { + // can't use AssertIncludeQuery here, see #18191 + return AssertQuery( + isAsync, + ss => ss.Set() + .Include(g => g.Squad) + .Include(g => g.Weapons) + .Select(g => new { gear = g, weapon = g.Weapons.OrderBy(w => w.Id).FirstOrDefault() }), + elementSorter: e => e.gear.Nickname, + elementAsserter: (e, a) => + { + AssertEqual(e.gear, a.gear); + AssertEqual(e.gear.Squad, a.gear.Squad); + AssertCollection(e.gear.Weapons, a.gear.Weapons); + AssertEqual(e.weapon, a.weapon); + }); + } + protected GearsOfWarContext CreateContext() => Fixture.CreateContext(); protected virtual void ClearLog() diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.ResultOperators.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.ResultOperators.cs index f591745e0b0..95b1083b10b 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.ResultOperators.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.ResultOperators.cs @@ -1835,5 +1835,26 @@ public virtual Task Sum_over_explicit_cast_over_column(bool isAsync) o => (long?)o.OrderID); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Count_on_projection_with_client_eval(bool isAsync) + { + await AssertCount( + isAsync, + ss => ss.Set().Select(o => o.OrderID.ToString("000000"))); + + await AssertCount( + isAsync, + ss => ss.Set().Select(o => new { Id = o.OrderID.ToString("000000") })); + + await AssertCount( + isAsync, + ss => ss.Set().Select(o => new { Id = CodeFormat(o.OrderID) })); + } + + private static string CodeFormat(int str) + { + return str.ToString(); + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs index fcb1cd04fed..a05dae94343 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs @@ -934,9 +934,9 @@ public override async Task Complex_navigations_with_predicate_projected_into_ano WHERE (([l1].[Id] = [l2].[Id]) AND [l2].[Id] IS NOT NULL) AND (([l2].[Id] <> 7) OR [l2].[Id] IS NULL)"); } - public override void Optional_navigation_projected_into_DTO() + public override async Task Optional_navigation_projected_into_DTO(bool isAsync) { - base.Optional_navigation_projected_into_DTO(); + await base.Optional_navigation_projected_into_DTO(isAsync); AssertSql( @"SELECT [l].[Id], [l].[Name], CASE @@ -2061,9 +2061,9 @@ public override async Task SelectMany_with_nested_required_navigation_filter_and WHERE [t].[Id] IS NOT NULL"); } - public override void SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany() + public override async Task SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(bool isAsync) { - base.SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(); + await base.SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(isAsync); AssertSql( @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t].[Id2], [t].[Date0], [t].[Level1_Optional_Id0], [t].[Level1_Required_Id0], [t].[Name2], [t].[OneToMany_Optional_Inverse2Id0], [t].[OneToMany_Optional_Self_Inverse2Id0], [t].[OneToMany_Required_Inverse2Id0], [t].[OneToMany_Required_Self_Inverse2Id0], [t].[OneToOne_Optional_PK_Inverse2Id0], [t].[OneToOne_Optional_Self2Id0] @@ -3097,9 +3097,9 @@ public override async Task Member_doesnt_get_pushed_down_into_subquery_with_resu WHERE [l0].[Id] < 3"); } - public override void Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy() + public override async Task Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(bool isAsync) { - base.Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(); + await base.Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(isAsync); AssertSql( ""); @@ -3217,9 +3217,9 @@ public override async Task Project_navigation_and_collection(bool isAsync) ORDER BY [l].[Id], [l1].[Id]"); } - public override void Include_inside_subquery() + public override async Task Include_inside_subquery(bool isAsync) { - base.Include_inside_subquery(); + await base.Include_inside_subquery(isAsync); AssertSql( @"SELECT [l].[Id], [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [t].[Id0], [t].[Level2_Optional_Id], [t].[Level2_Required_Id], [t].[Name0], [t].[OneToMany_Optional_Inverse3Id], [t].[OneToMany_Optional_Self_Inverse3Id], [t].[OneToMany_Required_Inverse3Id], [t].[OneToMany_Required_Self_Inverse3Id], [t].[OneToOne_Optional_PK_Inverse3Id], [t].[OneToOne_Optional_Self3Id] @@ -3600,9 +3600,9 @@ public override async Task Multiple_SelectMany_navigation_property_followed_by_s ORDER BY [l].[Id], [l0].[Id], [l1].[Id], [l2].[Id]"); } - public override void SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation() + public override async Task SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation(bool isAsync) { - base.SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation(); + await base.SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation(isAsync); AssertSql( @"SELECT [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], [l].[Id], [l1].[Id], [l1].[Level2_Optional_Id], [l1].[Level2_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse3Id], [l1].[OneToMany_Optional_Self_Inverse3Id], [l1].[OneToMany_Required_Inverse3Id], [l1].[OneToMany_Required_Self_Inverse3Id], [l1].[OneToOne_Optional_PK_Inverse3Id], [l1].[OneToOne_Optional_Self3Id], [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Optional_Self_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToMany_Required_Self_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[OneToOne_Optional_Self3Id] @@ -4139,9 +4139,9 @@ public override void IncludeCollection7() ORDER BY [l].[Id], [t].[Id], [t0].[Id]"); } - public override void IncludeCollection8() + public override async Task IncludeCollection8(bool isAsync) { - base.IncludeCollection8(); + await base.IncludeCollection8(isAsync); AssertSql( @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [t].[Id0], [t].[Level2_Optional_Id], [t].[Level2_Required_Id], [t].[Name0], [t].[OneToMany_Optional_Inverse3Id], [t].[OneToMany_Optional_Self_Inverse3Id], [t].[OneToMany_Required_Inverse3Id], [t].[OneToMany_Required_Self_Inverse3Id], [t].[OneToOne_Optional_PK_Inverse3Id], [t].[OneToOne_Optional_Self3Id], [t].[Id1], [t].[Level3_Optional_Id], [t].[Level3_Required_Id], [t].[Name1], [t].[OneToMany_Optional_Inverse4Id], [t].[OneToMany_Optional_Self_Inverse4Id], [t].[OneToMany_Required_Inverse4Id], [t].[OneToMany_Required_Self_Inverse4Id], [t].[OneToOne_Optional_PK_Inverse4Id], [t].[OneToOne_Optional_Self4Id] @@ -4160,9 +4160,9 @@ SELECT COUNT(*) ORDER BY [l].[Id], [t].[Id]"); } - public override void Include_with_all_method_include_gets_ignored() + public override async Task Include_with_all_method_include_gets_ignored(bool isAsnc) { - base.Include_with_all_method_include_gets_ignored(); + await base.Include_with_all_method_include_gets_ignored(isAsnc); AssertSql( @"SELECT CASE @@ -4241,6 +4241,40 @@ public override void Member_pushdown_chain_3_levels_deep() ORDER BY [l].[Id]"); } + public override void Member_pushdown_chain_3_levels_deep_entity() + { + base.Member_pushdown_chain_3_levels_deep_entity(); + + AssertSql( + @"SELECT [t4].[Id], [t4].[Level3_Optional_Id], [t4].[Level3_Required_Id], [t4].[Name], [t4].[OneToMany_Optional_Inverse4Id], [t4].[OneToMany_Optional_Self_Inverse4Id], [t4].[OneToMany_Required_Inverse4Id], [t4].[OneToMany_Required_Self_Inverse4Id], [t4].[OneToOne_Optional_PK_Inverse4Id], [t4].[OneToOne_Optional_Self4Id] +FROM [LevelOne] AS [l] +LEFT JOIN ( + SELECT [t3].[Id], [t3].[Level3_Optional_Id], [t3].[Level3_Required_Id], [t3].[Name], [t3].[OneToMany_Optional_Inverse4Id], [t3].[OneToMany_Optional_Self_Inverse4Id], [t3].[OneToMany_Required_Inverse4Id], [t3].[OneToMany_Required_Self_Inverse4Id], [t3].[OneToOne_Optional_PK_Inverse4Id], [t3].[OneToOne_Optional_Self4Id], [t3].[Id0], [t3].[Level1_Optional_Id] + FROM ( + SELECT [t2].[Id], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Optional_Self_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToMany_Required_Self_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[OneToOne_Optional_Self4Id], [l0].[Id] AS [Id0], [l0].[Level1_Optional_Id], ROW_NUMBER() OVER(PARTITION BY [l0].[Level1_Optional_Id] ORDER BY [l0].[Id]) AS [row] + FROM [LevelTwo] AS [l0] + LEFT JOIN ( + SELECT [t1].[Id], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Optional_Self_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToMany_Required_Self_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[OneToOne_Optional_Self4Id], [t1].[Id0], [t1].[Level2_Required_Id] + FROM ( + SELECT [t0].[Id], [t0].[Level3_Optional_Id], [t0].[Level3_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse4Id], [t0].[OneToMany_Optional_Self_Inverse4Id], [t0].[OneToMany_Required_Inverse4Id], [t0].[OneToMany_Required_Self_Inverse4Id], [t0].[OneToOne_Optional_PK_Inverse4Id], [t0].[OneToOne_Optional_Self4Id], [l1].[Id] AS [Id0], [l1].[Level2_Required_Id], ROW_NUMBER() OVER(PARTITION BY [l1].[Level2_Required_Id] ORDER BY [l1].[Id]) AS [row] + FROM [LevelThree] AS [l1] + LEFT JOIN ( + SELECT [t].[Id], [t].[Level3_Optional_Id], [t].[Level3_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse4Id], [t].[OneToMany_Optional_Self_Inverse4Id], [t].[OneToMany_Required_Inverse4Id], [t].[OneToMany_Required_Self_Inverse4Id], [t].[OneToOne_Optional_PK_Inverse4Id], [t].[OneToOne_Optional_Self4Id] + FROM ( + SELECT [l2].[Id], [l2].[Level3_Optional_Id], [l2].[Level3_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse4Id], [l2].[OneToMany_Optional_Self_Inverse4Id], [l2].[OneToMany_Required_Inverse4Id], [l2].[OneToMany_Required_Self_Inverse4Id], [l2].[OneToOne_Optional_PK_Inverse4Id], [l2].[OneToOne_Optional_Self4Id], ROW_NUMBER() OVER(PARTITION BY [l2].[Level3_Required_Id] ORDER BY [l2].[Id]) AS [row] + FROM [LevelFour] AS [l2] + ) AS [t] + WHERE [t].[row] <= 1 + ) AS [t0] ON [l1].[Id] = [t0].[Level3_Required_Id] + ) AS [t1] + WHERE [t1].[row] <= 1 + ) AS [t2] ON [l0].[Id] = [t2].[Level2_Required_Id] + ) AS [t3] + WHERE [t3].[row] <= 1 +) AS [t4] ON [l].[Id] = [t4].[Level1_Optional_Id] +ORDER BY [l].[Id]"); + } + public override void Member_pushdown_with_collection_navigation_in_the_middle() { base.Member_pushdown_with_collection_navigation_in_the_middle(); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 85e61f23ea0..fced17751e0 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Xunit.Abstractions; @@ -1220,9 +1221,9 @@ public override async Task Select_coalesce_with_anonymous_types(bool isAsync) ORDER BY [g].[Nickname]"); } - public override void Where_compare_anonymous_types() + public override async Task Where_compare_anonymous_types(bool isAsync) { - base.Where_compare_anonymous_types(); + await base.Where_compare_anonymous_types(isAsync); AssertSql( ""); @@ -1510,9 +1511,9 @@ public override async Task Where_subquery_distinct_singleordefault_boolean_with_ ORDER BY [g].[Nickname]"); } - public override void Where_subquery_distinct_lastordefault_boolean() + public override async Task Where_subquery_distinct_lastordefault_boolean(bool isAsync) { - base.Where_subquery_distinct_lastordefault_boolean(); + await base.Where_subquery_distinct_lastordefault_boolean(isAsync); AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] @@ -1528,9 +1529,9 @@ public override void Where_subquery_distinct_lastordefault_boolean() ORDER BY [g].[Nickname]"); } - public override void Where_subquery_distinct_last_boolean() + public override async Task Where_subquery_distinct_last_boolean(bool isAsync) { - base.Where_subquery_distinct_last_boolean(); + await base.Where_subquery_distinct_last_boolean(isAsync); AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] @@ -1665,9 +1666,9 @@ UNION ALL ) AS [t]"); } - public override void Concat_with_scalar_projection() + public override async Task Concat_with_scalar_projection(bool isAsync) { - base.Concat_with_scalar_projection(); + await base.Concat_with_scalar_projection(isAsync); AssertSql( @"SELECT [t].[Nickname] @@ -2845,24 +2846,17 @@ public override async Task DateTimeOffset_DateAdd_AddMilliseconds(bool isAsync) FROM [Missions] AS [m]"); } - public override void Where_datetimeoffset_milliseconds_parameter_and_constant() + public override async Task Where_datetimeoffset_milliseconds_parameter_and_constant(bool isAsync) { - base.Where_datetimeoffset_milliseconds_parameter_and_constant(); + await base.Where_datetimeoffset_milliseconds_parameter_and_constant(isAsync); AssertSql( - @"@__dateTimeOffset_0='1902-01-02T10:00:00.1234567+01:30' - -SELECT COUNT(*) -FROM [Missions] AS [m] -WHERE ([m].[Timeline] = @__dateTimeOffset_0) AND @__dateTimeOffset_0 IS NOT NULL", - // @"SELECT COUNT(*) FROM [Missions] AS [m] WHERE [m].[Timeline] = '1902-01-02T10:00:00.1234567+01:30'"); } - public override async Task Orderby_added_for_client_side_GroupJoin_composite_dependent_to_principal_LOJ_when_incomplete_key_is_used( - bool isAsync) + public override async Task Orderby_added_for_client_side_GroupJoin_composite_dependent_to_principal_LOJ_when_incomplete_key_is_used(bool isAsync) { await base.Orderby_added_for_client_side_GroupJoin_composite_dependent_to_principal_LOJ_when_incomplete_key_is_used(isAsync); @@ -3018,9 +3012,9 @@ public override async Task Contains_with_local_nullable_guid_list_closure(bool i WHERE [t].[Id] IN ('d2c26679-562b-44d1-ab96-23d1775e0926', '23cbcf9b-ce14-45cf-aafa-2c2667ebfdd3', 'ab1b82d7-88db-42bd-a132-7eef9aa68af4')"); } - public override void Unnecessary_include_doesnt_get_added_complex_when_projecting_EF_Property() + public override async Task Unnecessary_include_doesnt_get_added_complex_when_projecting_EF_Property(bool isAsync) { - base.Unnecessary_include_doesnt_get_added_complex_when_projecting_EF_Property(); + await base.Unnecessary_include_doesnt_get_added_complex_when_projecting_EF_Property(isAsync); AssertSql( @"SELECT [g].[FullName] @@ -3029,9 +3023,9 @@ public override void Unnecessary_include_doesnt_get_added_complex_when_projectin ORDER BY [g].[Rank]"); } - public override void Multiple_order_bys_are_properly_lifted_from_subquery_created_by_include() + public override async Task Multiple_order_bys_are_properly_lifted_from_subquery_created_by_include(bool isAsync) { - base.Multiple_order_bys_are_properly_lifted_from_subquery_created_by_include(); + await base.Multiple_order_bys_are_properly_lifted_from_subquery_created_by_include(isAsync); AssertSql( @"SELECT [g].[FullName] @@ -3040,9 +3034,9 @@ public override void Multiple_order_bys_are_properly_lifted_from_subquery_create ORDER BY [g].[FullName]"); } - public override void Order_by_is_properly_lifted_from_subquery_with_same_order_by_in_the_outer_query() + public override async Task Order_by_is_properly_lifted_from_subquery_with_same_order_by_in_the_outer_query(bool isAsync) { - base.Order_by_is_properly_lifted_from_subquery_with_same_order_by_in_the_outer_query(); + await base.Order_by_is_properly_lifted_from_subquery_with_same_order_by_in_the_outer_query(isAsync); AssertSql( @"SELECT [g].[FullName] @@ -3051,9 +3045,9 @@ public override void Order_by_is_properly_lifted_from_subquery_with_same_order_b ORDER BY [g].[FullName]"); } - public override void Where_is_properly_lifted_from_subquery_created_by_include() + public override async Task Where_is_properly_lifted_from_subquery_created_by_include(bool isAsync) { - base.Where_is_properly_lifted_from_subquery_created_by_include(); + await base.Where_is_properly_lifted_from_subquery_created_by_include(isAsync); AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note] @@ -3063,9 +3057,9 @@ public override void Where_is_properly_lifted_from_subquery_created_by_include() ORDER BY [g].[FullName]"); } - public override void Subquery_is_lifted_from_main_from_clause_of_SelectMany() + public override async Task Subquery_is_lifted_from_main_from_clause_of_SelectMany(bool isAsync) { - base.Subquery_is_lifted_from_main_from_clause_of_SelectMany(); + await base.Subquery_is_lifted_from_main_from_clause_of_SelectMany(isAsync); AssertSql( @"SELECT [g].[FullName] AS [Name1], [t].[FullName] AS [Name2] @@ -3128,9 +3122,9 @@ public override async Task Subquery_containing_join_gets_lifted_clashing_names(b ORDER BY [g].[Nickname], [t0].[Id]"); } - public override void Subquery_created_by_include_gets_lifted_nested() + public override async Task Subquery_created_by_include_gets_lifted_nested(bool isAsync) { - base.Subquery_created_by_include_gets_lifted_nested(); + await base.Subquery_created_by_include_gets_lifted_nested(isAsync); AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [c].[Name], [c].[Location], [c].[Nation] @@ -3307,9 +3301,9 @@ public override async Task Client_method_on_collection_navigation_in_outer_join_ WHERE @_outer_FullName = [w].[OwnerFullName]"); } - public override void Member_access_on_derived_entity_using_cast() + public override async Task Member_access_on_derived_entity_using_cast(bool isAsync) { - base.Member_access_on_derived_entity_using_cast(); + await base.Member_access_on_derived_entity_using_cast(isAsync); AssertSql( @"SELECT [f].[Name], [f].[Eradicated] @@ -3318,9 +3312,9 @@ public override void Member_access_on_derived_entity_using_cast() ORDER BY [f].[Name]"); } - public override void Member_access_on_derived_materialized_entity_using_cast() + public override async Task Member_access_on_derived_materialized_entity_using_cast(bool isAsync) { - base.Member_access_on_derived_materialized_entity_using_cast(); + await base.Member_access_on_derived_materialized_entity_using_cast(isAsync); AssertSql( @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] @@ -3329,9 +3323,9 @@ public override void Member_access_on_derived_materialized_entity_using_cast() ORDER BY [f].[Name]"); } - public override void Member_access_on_derived_entity_using_cast_and_let() + public override async Task Member_access_on_derived_entity_using_cast_and_let(bool isAsync) { - base.Member_access_on_derived_entity_using_cast_and_let(); + await base.Member_access_on_derived_entity_using_cast_and_let(isAsync); AssertSql( @"SELECT [f].[Name], [f].[Eradicated] @@ -3340,9 +3334,9 @@ public override void Member_access_on_derived_entity_using_cast_and_let() ORDER BY [f].[Name]"); } - public override void Property_access_on_derived_entity_using_cast() + public override async Task Property_access_on_derived_entity_using_cast(bool isAsync) { - base.Property_access_on_derived_entity_using_cast(); + await base.Property_access_on_derived_entity_using_cast(isAsync); AssertSql( @"SELECT [f].[Name], [f].[Eradicated] @@ -3351,9 +3345,9 @@ public override void Property_access_on_derived_entity_using_cast() ORDER BY [f].[Name]"); } - public override void Navigation_access_on_derived_entity_using_cast() + public override async Task Navigation_access_on_derived_entity_using_cast(bool isAsync) { - base.Navigation_access_on_derived_entity_using_cast(); + await base.Navigation_access_on_derived_entity_using_cast(isAsync); AssertSql( @"SELECT [f].[Name], [t].[ThreatLevel] AS [Threat] @@ -3367,9 +3361,9 @@ public override void Navigation_access_on_derived_entity_using_cast() ORDER BY [f].[Name]"); } - public override void Navigation_access_on_derived_materialized_entity_using_cast() + public override async Task Navigation_access_on_derived_materialized_entity_using_cast(bool isAsync) { - base.Navigation_access_on_derived_materialized_entity_using_cast(); + await base.Navigation_access_on_derived_materialized_entity_using_cast(isAsync); AssertSql( @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[ThreatLevel] AS [Threat] @@ -3383,9 +3377,9 @@ public override void Navigation_access_on_derived_materialized_entity_using_cast ORDER BY [f].[Name]"); } - public override void Navigation_access_via_EFProperty_on_derived_entity_using_cast() + public override async Task Navigation_access_via_EFProperty_on_derived_entity_using_cast(bool isAsync) { - base.Navigation_access_via_EFProperty_on_derived_entity_using_cast(); + await base.Navigation_access_via_EFProperty_on_derived_entity_using_cast(isAsync); AssertSql( @"SELECT [f].[Name], [t].[ThreatLevel] AS [Threat] @@ -3399,9 +3393,9 @@ public override void Navigation_access_via_EFProperty_on_derived_entity_using_ca ORDER BY [f].[Name]"); } - public override void Navigation_access_fk_on_derived_entity_using_cast() + public override async Task Navigation_access_fk_on_derived_entity_using_cast(bool isAsync) { - base.Navigation_access_fk_on_derived_entity_using_cast(); + await base.Navigation_access_fk_on_derived_entity_using_cast(isAsync); AssertSql( @"SELECT [f].[Name], [t].[Name] AS [CommanderName] @@ -3415,9 +3409,9 @@ public override void Navigation_access_fk_on_derived_entity_using_cast() ORDER BY [f].[Name]"); } - public override void Collection_navigation_access_on_derived_entity_using_cast() + public override async Task Collection_navigation_access_on_derived_entity_using_cast(bool isAsync) { - base.Collection_navigation_access_on_derived_entity_using_cast(); + await base.Collection_navigation_access_on_derived_entity_using_cast(isAsync); AssertSql( @"SELECT [f].[Name], ( @@ -3429,9 +3423,9 @@ SELECT COUNT(*) ORDER BY [f].[Name]"); } - public override void Collection_navigation_access_on_derived_entity_using_cast_in_SelectMany() + public override async Task Collection_navigation_access_on_derived_entity_using_cast_in_SelectMany(bool isAsync) { - base.Collection_navigation_access_on_derived_entity_using_cast_in_SelectMany(); + await base.Collection_navigation_access_on_derived_entity_using_cast_in_SelectMany(isAsync); AssertSql( @"SELECT [f].[Name], [t].[Name] AS [LeaderName] @@ -3445,9 +3439,9 @@ public override void Collection_navigation_access_on_derived_entity_using_cast_i ORDER BY [t].[Name]"); } - public override void Include_on_derived_entity_using_OfType() + public override async Task Include_on_derived_entity_using_OfType(bool isAsync) { - base.Include_on_derived_entity_using_OfType(); + await base.Include_on_derived_entity_using_OfType(isAsync); AssertSql( @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Name], [t0].[Discriminator], [t0].[LocustHordeId], [t0].[ThreatLevel], [t0].[DefeatedByNickname], [t0].[DefeatedBySquadId], [t0].[HighCommandId] @@ -3466,106 +3460,106 @@ public override void Include_on_derived_entity_using_OfType() ORDER BY [f].[Name], [f].[Id], [t0].[Name]"); } - public override void Include_on_derived_entity_using_subquery_with_cast() - { - base.Include_on_derived_entity_using_subquery_with_cast(); - - AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId] -FROM [Factions] AS [f] -LEFT JOIN ( - SELECT [f.Commander].* - FROM [LocustLeaders] AS [f.Commander] - WHERE [f.Commander].[Discriminator] = N'LocustCommander' -) AS [t] ON ([f].[Discriminator] = N'LocustHorde') AND ([f].[CommanderName] = [t].[Name]) -WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') -ORDER BY [f].[Name], [f].[Id]", - // - @"SELECT [f.Leaders].[Name], [f.Leaders].[Discriminator], [f.Leaders].[LocustHordeId], [f.Leaders].[ThreatLevel], [f.Leaders].[DefeatedByNickname], [f.Leaders].[DefeatedBySquadId], [f.Leaders].[HighCommandId] -FROM [LocustLeaders] AS [f.Leaders] -INNER JOIN ( - SELECT DISTINCT [f0].[Id], [f0].[Name] - FROM [Factions] AS [f0] - LEFT JOIN ( - SELECT [f.Commander0].* - FROM [LocustLeaders] AS [f.Commander0] - WHERE [f.Commander0].[Discriminator] = N'LocustCommander' - ) AS [t0] ON ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[CommanderName] = [t0].[Name]) - WHERE ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[Discriminator] = N'LocustHorde') -) AS [t1] ON [f.Leaders].[LocustHordeId] = [t1].[Id] -WHERE [f.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') -ORDER BY [t1].[Name], [t1].[Id]"); - } - - public override void Include_on_derived_entity_using_subquery_with_cast_AsNoTracking() - { - base.Include_on_derived_entity_using_subquery_with_cast_AsNoTracking(); - - AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId] -FROM [Factions] AS [f] -LEFT JOIN ( - SELECT [f.Commander].* - FROM [LocustLeaders] AS [f.Commander] - WHERE [f.Commander].[Discriminator] = N'LocustCommander' -) AS [t] ON ([f].[Discriminator] = N'LocustHorde') AND ([f].[CommanderName] = [t].[Name]) -WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') -ORDER BY [f].[Name], [f].[Id]", - // - @"SELECT [f.Leaders].[Name], [f.Leaders].[Discriminator], [f.Leaders].[LocustHordeId], [f.Leaders].[ThreatLevel], [f.Leaders].[DefeatedByNickname], [f.Leaders].[DefeatedBySquadId], [f.Leaders].[HighCommandId] -FROM [LocustLeaders] AS [f.Leaders] -INNER JOIN ( - SELECT DISTINCT [f0].[Id], [f0].[Name] - FROM [Factions] AS [f0] - LEFT JOIN ( - SELECT [f.Commander0].* - FROM [LocustLeaders] AS [f.Commander0] - WHERE [f.Commander0].[Discriminator] = N'LocustCommander' - ) AS [t0] ON ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[CommanderName] = [t0].[Name]) - WHERE ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[Discriminator] = N'LocustHorde') -) AS [t1] ON [f.Leaders].[LocustHordeId] = [t1].[Id] -WHERE [f.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') -ORDER BY [t1].[Name], [t1].[Id]"); - } - - public override void Include_on_derived_entity_using_subquery_with_cast_cross_product_base_entity() - { - base.Include_on_derived_entity_using_subquery_with_cast_cross_product_base_entity(); - - AssertSql( - @"SELECT [f2].[Id], [f2].[CapitalName], [f2].[Discriminator], [f2].[Name], [f2].[CommanderName], [f2].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [ff].[Id], [ff].[CapitalName], [ff].[Discriminator], [ff].[Name], [ff].[CommanderName], [ff].[Eradicated], [ff.Capital].[Name], [ff.Capital].[Location], [ff.Capital].[Nation] -FROM [Factions] AS [f2] -LEFT JOIN ( - SELECT [f2.Commander].* - FROM [LocustLeaders] AS [f2.Commander] - WHERE [f2.Commander].[Discriminator] = N'LocustCommander' -) AS [t] ON ([f2].[Discriminator] = N'LocustHorde') AND ([f2].[CommanderName] = [t].[Name]) -CROSS JOIN [Factions] AS [ff] -LEFT JOIN [Cities] AS [ff.Capital] ON [ff].[CapitalName] = [ff.Capital].[Name] -WHERE ([f2].[Discriminator] = N'LocustHorde') AND ([f2].[Discriminator] = N'LocustHorde') -ORDER BY [f2].[Name], [ff].[Name], [f2].[Id]", - // - @"SELECT [f2.Leaders].[Name], [f2.Leaders].[Discriminator], [f2.Leaders].[LocustHordeId], [f2.Leaders].[ThreatLevel], [f2.Leaders].[DefeatedByNickname], [f2.Leaders].[DefeatedBySquadId], [f2.Leaders].[HighCommandId] -FROM [LocustLeaders] AS [f2.Leaders] -INNER JOIN ( - SELECT DISTINCT [f20].[Id], [f20].[Name], [ff0].[Name] AS [Name0] - FROM [Factions] AS [f20] - LEFT JOIN ( - SELECT [f2.Commander0].* - FROM [LocustLeaders] AS [f2.Commander0] - WHERE [f2.Commander0].[Discriminator] = N'LocustCommander' - ) AS [t0] ON ([f20].[Discriminator] = N'LocustHorde') AND ([f20].[CommanderName] = [t0].[Name]) - CROSS JOIN [Factions] AS [ff0] - LEFT JOIN [Cities] AS [ff.Capital0] ON [ff0].[CapitalName] = [ff.Capital0].[Name] - WHERE ([f20].[Discriminator] = N'LocustHorde') AND ([f20].[Discriminator] = N'LocustHorde') -) AS [t1] ON [f2.Leaders].[LocustHordeId] = [t1].[Id] -WHERE [f2.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') -ORDER BY [t1].[Name], [t1].[Name0], [t1].[Id]"); - } - - public override void Distinct_on_subquery_doesnt_get_lifted() - { - base.Distinct_on_subquery_doesnt_get_lifted(); +// public override async Task Include_on_derived_entity_using_subquery_with_cast(bool isAsync) +// { +// await base.Include_on_derived_entity_using_subquery_with_cast(isAsync); + +// AssertSql( +// @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId] +//FROM [Factions] AS [f] +//LEFT JOIN ( +// SELECT [f.Commander].* +// FROM [LocustLeaders] AS [f.Commander] +// WHERE [f.Commander].[Discriminator] = N'LocustCommander' +//) AS [t] ON ([f].[Discriminator] = N'LocustHorde') AND ([f].[CommanderName] = [t].[Name]) +//WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') +//ORDER BY [f].[Name], [f].[Id]", +// // +// @"SELECT [f.Leaders].[Name], [f.Leaders].[Discriminator], [f.Leaders].[LocustHordeId], [f.Leaders].[ThreatLevel], [f.Leaders].[DefeatedByNickname], [f.Leaders].[DefeatedBySquadId], [f.Leaders].[HighCommandId] +//FROM [LocustLeaders] AS [f.Leaders] +//INNER JOIN ( +// SELECT DISTINCT [f0].[Id], [f0].[Name] +// FROM [Factions] AS [f0] +// LEFT JOIN ( +// SELECT [f.Commander0].* +// FROM [LocustLeaders] AS [f.Commander0] +// WHERE [f.Commander0].[Discriminator] = N'LocustCommander' +// ) AS [t0] ON ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[CommanderName] = [t0].[Name]) +// WHERE ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[Discriminator] = N'LocustHorde') +//) AS [t1] ON [f.Leaders].[LocustHordeId] = [t1].[Id] +//WHERE [f.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') +//ORDER BY [t1].[Name], [t1].[Id]"); +// } + +// public override async Task Include_on_derived_entity_using_subquery_with_cast_AsNoTracking(bool isAsync) +// { +// await base.Include_on_derived_entity_using_subquery_with_cast_AsNoTracking(isAsync); + +// AssertSql( +// @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId] +//FROM [Factions] AS [f] +//LEFT JOIN ( +// SELECT [f.Commander].* +// FROM [LocustLeaders] AS [f.Commander] +// WHERE [f.Commander].[Discriminator] = N'LocustCommander' +//) AS [t] ON ([f].[Discriminator] = N'LocustHorde') AND ([f].[CommanderName] = [t].[Name]) +//WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') +//ORDER BY [f].[Name], [f].[Id]", +// // +// @"SELECT [f.Leaders].[Name], [f.Leaders].[Discriminator], [f.Leaders].[LocustHordeId], [f.Leaders].[ThreatLevel], [f.Leaders].[DefeatedByNickname], [f.Leaders].[DefeatedBySquadId], [f.Leaders].[HighCommandId] +//FROM [LocustLeaders] AS [f.Leaders] +//INNER JOIN ( +// SELECT DISTINCT [f0].[Id], [f0].[Name] +// FROM [Factions] AS [f0] +// LEFT JOIN ( +// SELECT [f.Commander0].* +// FROM [LocustLeaders] AS [f.Commander0] +// WHERE [f.Commander0].[Discriminator] = N'LocustCommander' +// ) AS [t0] ON ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[CommanderName] = [t0].[Name]) +// WHERE ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[Discriminator] = N'LocustHorde') +//) AS [t1] ON [f.Leaders].[LocustHordeId] = [t1].[Id] +//WHERE [f.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') +//ORDER BY [t1].[Name], [t1].[Id]"); +// } + +// public override void Include_on_derived_entity_using_subquery_with_cast_cross_product_base_entity() +// { +// base.Include_on_derived_entity_using_subquery_with_cast_cross_product_base_entity(); + +// AssertSql( +// @"SELECT [f2].[Id], [f2].[CapitalName], [f2].[Discriminator], [f2].[Name], [f2].[CommanderName], [f2].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [ff].[Id], [ff].[CapitalName], [ff].[Discriminator], [ff].[Name], [ff].[CommanderName], [ff].[Eradicated], [ff.Capital].[Name], [ff.Capital].[Location], [ff.Capital].[Nation] +//FROM [Factions] AS [f2] +//LEFT JOIN ( +// SELECT [f2.Commander].* +// FROM [LocustLeaders] AS [f2.Commander] +// WHERE [f2.Commander].[Discriminator] = N'LocustCommander' +//) AS [t] ON ([f2].[Discriminator] = N'LocustHorde') AND ([f2].[CommanderName] = [t].[Name]) +//CROSS JOIN [Factions] AS [ff] +//LEFT JOIN [Cities] AS [ff.Capital] ON [ff].[CapitalName] = [ff.Capital].[Name] +//WHERE ([f2].[Discriminator] = N'LocustHorde') AND ([f2].[Discriminator] = N'LocustHorde') +//ORDER BY [f2].[Name], [ff].[Name], [f2].[Id]", +// // +// @"SELECT [f2.Leaders].[Name], [f2.Leaders].[Discriminator], [f2.Leaders].[LocustHordeId], [f2.Leaders].[ThreatLevel], [f2.Leaders].[DefeatedByNickname], [f2.Leaders].[DefeatedBySquadId], [f2.Leaders].[HighCommandId] +//FROM [LocustLeaders] AS [f2.Leaders] +//INNER JOIN ( +// SELECT DISTINCT [f20].[Id], [f20].[Name], [ff0].[Name] AS [Name0] +// FROM [Factions] AS [f20] +// LEFT JOIN ( +// SELECT [f2.Commander0].* +// FROM [LocustLeaders] AS [f2.Commander0] +// WHERE [f2.Commander0].[Discriminator] = N'LocustCommander' +// ) AS [t0] ON ([f20].[Discriminator] = N'LocustHorde') AND ([f20].[CommanderName] = [t0].[Name]) +// CROSS JOIN [Factions] AS [ff0] +// LEFT JOIN [Cities] AS [ff.Capital0] ON [ff0].[CapitalName] = [ff.Capital0].[Name] +// WHERE ([f20].[Discriminator] = N'LocustHorde') AND ([f20].[Discriminator] = N'LocustHorde') +//) AS [t1] ON [f2.Leaders].[LocustHordeId] = [t1].[Id] +//WHERE [f2.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') +//ORDER BY [t1].[Name], [t1].[Name0], [t1].[Id]"); +// } + + public override async Task Distinct_on_subquery_doesnt_get_lifted(bool isAsync) + { + await base.Distinct_on_subquery_doesnt_get_lifted(isAsync); AssertSql( @"SELECT [t].[HasSoulPatch] @@ -3576,9 +3570,9 @@ public override void Distinct_on_subquery_doesnt_get_lifted() ) AS [t]"); } - public override void Cast_result_operator_on_subquery_is_properly_lifted_to_a_convert() + public override async Task Cast_result_operator_on_subquery_is_properly_lifted_to_a_convert(bool isAsync) { - base.Cast_result_operator_on_subquery_is_properly_lifted_to_a_convert(); + await base.Cast_result_operator_on_subquery_is_properly_lifted_to_a_convert(isAsync); AssertSql( @"SELECT [f].[Eradicated] @@ -3586,9 +3580,9 @@ public override void Cast_result_operator_on_subquery_is_properly_lifted_to_a_co WHERE [f].[Discriminator] = N'LocustHorde'"); } - public override void Comparing_two_collection_navigations_composite_key() + public override async Task Comparing_two_collection_navigations_composite_key(bool isAsync) { - base.Comparing_two_collection_navigations_composite_key(); + await base.Comparing_two_collection_navigations_composite_key(isAsync); AssertSql( @"SELECT [g].[Nickname] AS [Nickname1], [t].[Nickname] AS [Nickname2] @@ -3602,9 +3596,9 @@ public override void Comparing_two_collection_navigations_composite_key() ORDER BY [g].[Nickname]"); } - public override void Comparing_two_collection_navigations_inheritance() + public override async Task Comparing_two_collection_navigations_inheritance(bool isAsync) { - base.Comparing_two_collection_navigations_inheritance(); + await base.Comparing_two_collection_navigations_inheritance(isAsync); AssertSql( @"SELECT [f].[Name], [t].[Nickname] @@ -3627,9 +3621,9 @@ public override void Comparing_two_collection_navigations_inheritance() WHERE (([f].[Discriminator] = N'LocustHorde') AND (([f].[Discriminator] = N'LocustHorde') AND ([t].[HasSoulPatch] = CAST(1 AS bit)))) AND ((([t1].[Nickname] = [t].[Nickname]) AND [t1].[Nickname] IS NOT NULL) AND (([t1].[SquadId] = [t].[SquadId]) AND [t1].[SquadId] IS NOT NULL))"); } - public override void Comparing_entities_using_Equals_inheritance() + public override async Task Comparing_entities_using_Equals_inheritance(bool isAsync) { - base.Comparing_entities_using_Equals_inheritance(); + await base.Comparing_entities_using_Equals_inheritance(isAsync); AssertSql( @"SELECT [g].[Nickname] AS [Nickname1], [t].[Nickname] AS [Nickname2] @@ -3640,12 +3634,12 @@ public override void Comparing_entities_using_Equals_inheritance() WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') AND ([g0].[Discriminator] = N'Officer') ) AS [t] WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND (([g].[Nickname] = [t].[Nickname]) AND ([g].[SquadId] = [t].[SquadId])) -ORDER BY [g].[Nickname]"); +ORDER BY [g].[Nickname], [t].[Nickname]"); } - public override void Contains_on_nullable_array_produces_correct_sql() + public override async Task Contains_on_nullable_array_produces_correct_sql(bool isAsync) { - base.Contains_on_nullable_array_produces_correct_sql(); + await base.Contains_on_nullable_array_produces_correct_sql(isAsync); AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] @@ -3654,9 +3648,9 @@ public override void Contains_on_nullable_array_produces_correct_sql() WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND (([g].[SquadId] < 2) AND ([c].[Name] IN (N'Ephyra') OR [c].[Name] IS NULL))"); } - public override void Optional_navigation_with_collection_composite_key() + public override async Task Optional_navigation_with_collection_composite_key(bool isAsync) { - base.Optional_navigation_with_collection_composite_key(); + await base.Optional_navigation_with_collection_composite_key(isAsync); AssertSql( @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note] @@ -3672,9 +3666,9 @@ SELECT COUNT(*) WHERE ([g0].[Discriminator] IN (N'Gear', N'Officer') AND ([t0].[Nickname] IS NOT NULL AND ((([t0].[Nickname] = [g0].[LeaderNickname]) AND [g0].[LeaderNickname] IS NOT NULL) AND (([t0].[SquadId] = [g0].[LeaderSquadId]) AND [t0].[SquadId] IS NOT NULL)))) AND ([g0].[Nickname] = N'Dom')) > 0)"); } - public override void Select_null_conditional_with_inheritance() + public override async Task Select_null_conditional_with_inheritance(bool isAsync) { - base.Select_null_conditional_with_inheritance(); + await base.Select_null_conditional_with_inheritance(isAsync); AssertSql( @"SELECT CASE @@ -3685,9 +3679,9 @@ ELSE NULL WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde')"); } - public override void Select_null_conditional_with_inheritance_negative() + public override async Task Select_null_conditional_with_inheritance_negative(bool isAsync) { - base.Select_null_conditional_with_inheritance_negative(); + await base.Select_null_conditional_with_inheritance_negative(isAsync); AssertSql( @"SELECT CASE @@ -3698,9 +3692,9 @@ ELSE NULL WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde')"); } - public override void Project_collection_navigation_with_inheritance1() + public override async Task Project_collection_navigation_with_inheritance1(bool isAsync) { - base.Project_collection_navigation_with_inheritance1(); + await base.Project_collection_navigation_with_inheritance1(isAsync); AssertSql( @"SELECT [f].[Id], [t1].[Name], [t1].[Discriminator], [t1].[LocustHordeId], [t1].[ThreatLevel], [t1].[DefeatedByNickname], [t1].[DefeatedBySquadId], [t1].[HighCommandId] @@ -3724,9 +3718,9 @@ public override void Project_collection_navigation_with_inheritance1() ORDER BY [f].[Id], [t1].[Name]"); } - public override void Project_collection_navigation_with_inheritance2() + public override async Task Project_collection_navigation_with_inheritance2(bool isAsync) { - base.Project_collection_navigation_with_inheritance2(); + await base.Project_collection_navigation_with_inheritance2(isAsync); AssertSql( @"SELECT [f].[Id], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOrBirthName], [t1].[Discriminator], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank] @@ -3750,9 +3744,9 @@ public override void Project_collection_navigation_with_inheritance2() ORDER BY [f].[Id], [t1].[Nickname], [t1].[SquadId]"); } - public override void Project_collection_navigation_with_inheritance3() + public override async Task Project_collection_navigation_with_inheritance3(bool isAsync) { - base.Project_collection_navigation_with_inheritance3(); + await base.Project_collection_navigation_with_inheritance3(isAsync); AssertSql( @"SELECT [f].[Id], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOrBirthName], [t1].[Discriminator], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank] @@ -4986,9 +4980,9 @@ public override async Task Correlated_collections_with_funky_orderby_complex_sce ORDER BY [g].[HasSoulPatch], [g].[LeaderNickname], [g].[FullName], [g].[Nickname], [g].[SquadId], [t2].[FullName], [t2].[HasSoulPatch0] DESC, [t2].[Nickname], [t2].[SquadId], [t2].[IsAutomatic], [t2].[Name] DESC, [t2].[Id], [t2].[Nickname0], [t2].[SquadId0]"); } - public override void Correlated_collection_with_top_level_FirstOrDefault() + public override async Task Correlated_collection_with_top_level_FirstOrDefault(bool isAsync) { - base.Correlated_collection_with_top_level_FirstOrDefault(); + await base.Correlated_collection_with_top_level_FirstOrDefault(isAsync); AssertSql( @"SELECT [t].[Nickname], [t].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] @@ -5012,9 +5006,9 @@ public override async Task Correlated_collection_with_top_level_Count(bool isAsy WHERE [g].[Discriminator] IN (N'Gear', N'Officer')"); } - public override void Correlated_collection_with_top_level_Last_with_orderby_on_outer() + public override async Task Correlated_collection_with_top_level_Last_with_orderby_on_outer(bool isAsync) { - base.Correlated_collection_with_top_level_Last_with_orderby_on_outer(); + await base.Correlated_collection_with_top_level_Last_with_orderby_on_outer(isAsync); AssertSql( @"SELECT [t].[Nickname], [t].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] @@ -5028,9 +5022,9 @@ public override void Correlated_collection_with_top_level_Last_with_orderby_on_o ORDER BY [t].[FullName], [t].[Nickname], [t].[SquadId], [w].[Id]"); } - public override void Correlated_collection_with_top_level_Last_with_order_by_on_inner() + public override async Task Correlated_collection_with_top_level_Last_with_order_by_on_inner(bool isAsync) { - base.Correlated_collection_with_top_level_Last_with_order_by_on_inner(); + await base.Correlated_collection_with_top_level_Last_with_order_by_on_inner(isAsync); AssertSql( @"SELECT [t].[Nickname], [t].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] @@ -5621,9 +5615,9 @@ public override void Include_with_group_by_on_entity_navigation_with_inheritance ORDER BY [t3].[Nickname], [t3].[SquadId], [t3].[Id]"); } - public override void Streaming_correlated_collection_issue_11403() + public override async Task Streaming_correlated_collection_issue_11403(bool isAsync) { - base.Streaming_correlated_collection_issue_11403(); + await base.Streaming_correlated_collection_issue_11403(isAsync); AssertSql( @"SELECT TOP(1) [g].[FullName] @@ -6524,9 +6518,9 @@ public override async Task Include_collection_with_Cast_to_base(bool isAsync) ORDER BY [g].[Nickname], [g].[SquadId], [w].[Id]"); } - public override void Include_with_client_method_and_member_access_still_applies_includes() + public override async Task Include_with_client_method_and_member_access_still_applies_includes(bool isAsync) { - base.Include_with_client_method_and_member_access_still_applies_includes(); + await base.Include_with_client_method_and_member_access_still_applies_includes(isAsync); AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note] @@ -6535,9 +6529,9 @@ public override void Include_with_client_method_and_member_access_still_applies_ WHERE [g].[Discriminator] IN (N'Gear', N'Officer')"); } - public override void Include_with_projection_of_unmapped_property_still_gets_applied() + public override async Task Include_with_projection_of_unmapped_property_still_gets_applied(bool isAsync) { - base.Include_with_projection_of_unmapped_property_still_gets_applied(); + await base.Include_with_projection_of_unmapped_property_still_gets_applied(isAsync); AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] @@ -6731,44 +6725,41 @@ public override async Task Filter_with_new_Guid_closure(bool isAsync) WHERE [t].[Id] = @__p_0"); } - public override void OfTypeNav1() + public override async Task OfTypeNav1(bool isAsync) { - base.OfTypeNav1(); + await base.OfTypeNav1(isAsync); - // issue #16094 - // AssertSql( - // @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] - //FROM [Gears] AS [g] - //LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId]) - //LEFT JOIN [Tags] AS [o.Tag] ON ([g].[Nickname] = [o.Tag].[GearNickName]) AND ([g].[SquadId] = [o.Tag].[GearSquadId]) - //WHERE (([g].[Discriminator] = N'Officer') AND (([g.Tag].[Note] <> N'Foo') OR [g.Tag].[Note] IS NULL)) AND (([o.Tag].[Note] <> N'Bar') OR [o.Tag].[Note] IS NULL)"); + AssertSql( + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] +FROM [Gears] AS [g] +LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) +LEFT JOIN [Tags] AS [t0] ON (([g].[Nickname] = [t0].[GearNickName]) AND [t0].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t0].[GearSquadId]) AND [t0].[GearSquadId] IS NOT NULL) +WHERE (([g].[Discriminator] IN (N'Gear', N'Officer') AND (([t].[Note] <> N'Foo') OR [t].[Note] IS NULL)) AND ([g].[Discriminator] = N'Officer')) AND (([t0].[Note] <> N'Bar') OR [t0].[Note] IS NULL)"); } - public override void OfTypeNav2() + public override async Task OfTypeNav2(bool isAsync) { - base.OfTypeNav2(); + await base.OfTypeNav2(isAsync); - // issue #16094 - // AssertSql( - // @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] - //FROM [Gears] AS [g] - //LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId]) - //LEFT JOIN [Cities] AS [o.AssignedCity] ON [g].[AssignedCityName] = [o.AssignedCity].[Name] - //WHERE (([g].[Discriminator] = N'Officer') AND (([g.Tag].[Note] <> N'Foo') OR [g.Tag].[Note] IS NULL)) AND (([o.AssignedCity].[Location] <> 'Bar') OR [o.AssignedCity].[Location] IS NULL)"); + AssertSql( + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] +FROM [Gears] AS [g] +LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) +LEFT JOIN [Cities] AS [c] ON [g].[AssignedCityName] = [c].[Name] +WHERE (([g].[Discriminator] IN (N'Gear', N'Officer') AND (([t].[Note] <> N'Foo') OR [t].[Note] IS NULL)) AND ([g].[Discriminator] = N'Officer')) AND (([c].[Location] <> 'Bar') OR [c].[Location] IS NULL)"); } - public override void OfTypeNav3() + public override async Task OfTypeNav3(bool isAsync) { - base.OfTypeNav3(); + await base.OfTypeNav3(isAsync); - // issue #16094 - // AssertSql( - // @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] - //FROM [Gears] AS [g] - //LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId]) - //INNER JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] - //LEFT JOIN [Tags] AS [o.Tag] ON ([g].[Nickname] = [o.Tag].[GearNickName]) AND ([g].[SquadId] = [o.Tag].[GearSquadId]) - //WHERE (([g].[Discriminator] = N'Officer') AND (([g.Tag].[Note] <> N'Foo') OR [g.Tag].[Note] IS NULL)) AND (([o.Tag].[Note] <> N'Bar') OR [o.Tag].[Note] IS NULL)"); + AssertSql( + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] +FROM [Gears] AS [g] +LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) +INNER JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] +LEFT JOIN [Tags] AS [t0] ON (([g].[Nickname] = [t0].[GearNickName]) AND [t0].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t0].[GearSquadId]) AND [t0].[GearSquadId] IS NOT NULL) +WHERE (([g].[Discriminator] IN (N'Gear', N'Officer') AND (([t].[Note] <> N'Foo') OR [t].[Note] IS NULL)) AND ([g].[Discriminator] = N'Officer')) AND (([t0].[Note] <> N'Bar') OR [t0].[Note] IS NULL)"); } public override void Nav_rewrite_Distinct_with_convert() @@ -6787,55 +6778,52 @@ public override void Nav_rewrite_Distinct_with_convert_anonymous() @""); } - public override void Nav_rewrite_with_convert1() + public override async Task Nav_rewrite_with_convert1(bool isAsync) { - base.Nav_rewrite_with_convert1(); + await base.Nav_rewrite_with_convert1(isAsync); - // issue #15994 - // AssertSql( - // @"SELECT [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId] - //FROM [Factions] AS [f] - //LEFT JOIN [Cities] AS [f.Capital] ON [f].[CapitalName] = [f.Capital].[Name] - //LEFT JOIN ( - // SELECT [f.Capital.Commander].* - // FROM [LocustLeaders] AS [f.Capital.Commander] - // WHERE [f.Capital.Commander].[Discriminator] = N'LocustCommander' - //) AS [t] ON ([f].[Discriminator] = N'LocustHorde') AND ([f].[CommanderName] = [t].[Name]) - //WHERE ([f].[Discriminator] = N'LocustHorde') AND (([f.Capital].[Name] <> N'Foo') OR [f.Capital].[Name] IS NULL)"); + AssertSql( + @"SELECT [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId] +FROM [Factions] AS [f] +LEFT JOIN [Cities] AS [c] ON [f].[CapitalName] = [c].[Name] +LEFT JOIN ( + SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] + FROM [LocustLeaders] AS [l] + WHERE [l].[Discriminator] = N'LocustCommander' +) AS [t] ON [f].[CommanderName] = [t].[Name] +WHERE ([f].[Discriminator] = N'LocustHorde') AND (([c].[Name] <> N'Foo') OR [c].[Name] IS NULL)"); } - public override void Nav_rewrite_with_convert2() + public override async Task Nav_rewrite_with_convert2(bool isAsync) { - base.Nav_rewrite_with_convert2(); + await base.Nav_rewrite_with_convert2(isAsync); - // issue #15994 - // AssertSql( - // @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] - //FROM [Factions] AS [f] - //LEFT JOIN [Cities] AS [f.Capital] ON [f].[CapitalName] = [f.Capital].[Name] - //LEFT JOIN ( - // SELECT [f.Capital.Commander].* - // FROM [LocustLeaders] AS [f.Capital.Commander] - // WHERE [f.Capital.Commander].[Discriminator] = N'LocustCommander' - //) AS [t] ON ([f].[Discriminator] = N'LocustHorde') AND ([f].[CommanderName] = [t].[Name]) - //WHERE (([f].[Discriminator] = N'LocustHorde') AND (([f.Capital].[Name] <> N'Foo') OR [f.Capital].[Name] IS NULL)) AND (([t].[Name] <> N'Bar') OR [t].[Name] IS NULL)"); + AssertSql( + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] +FROM [Factions] AS [f] +LEFT JOIN [Cities] AS [c] ON [f].[CapitalName] = [c].[Name] +LEFT JOIN ( + SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] + FROM [LocustLeaders] AS [l] + WHERE [l].[Discriminator] = N'LocustCommander' +) AS [t] ON [f].[CommanderName] = [t].[Name] +WHERE (([f].[Discriminator] = N'LocustHorde') AND (([c].[Name] <> N'Foo') OR [c].[Name] IS NULL)) AND (([t].[Name] <> N'Bar') OR [t].[Name] IS NULL)"); } - public override void Nav_rewrite_with_convert3() + public override async Task Nav_rewrite_with_convert3(bool isAsync) { - base.Nav_rewrite_with_convert3(); + await base.Nav_rewrite_with_convert3(isAsync); - // issue #15994 - // AssertSql( - // @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] - //FROM [Factions] AS [f] - //LEFT JOIN [Cities] AS [f.Capital] ON [f].[CapitalName] = [f.Capital].[Name] - //LEFT JOIN ( - // SELECT [f.Capital.Commander].* - // FROM [LocustLeaders] AS [f.Capital.Commander] - // WHERE [f.Capital.Commander].[Discriminator] = N'LocustCommander' - //) AS [t] ON ([f].[Discriminator] = N'LocustHorde') AND ([f].[CommanderName] = [t].[Name]) - //WHERE (([f].[Discriminator] = N'LocustHorde') AND (([f.Capital].[Name] <> N'Foo') OR [f.Capital].[Name] IS NULL)) AND (([t].[Name] <> N'Bar') OR [t].[Name] IS NULL)"); + AssertSql( + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] +FROM [Factions] AS [f] +LEFT JOIN [Cities] AS [c] ON [f].[CapitalName] = [c].[Name] +LEFT JOIN ( + SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] + FROM [LocustLeaders] AS [l] + WHERE [l].[Discriminator] = N'LocustCommander' +) AS [t] ON [f].[CommanderName] = [t].[Name] +WHERE (([f].[Discriminator] = N'LocustHorde') AND (([c].[Name] <> N'Foo') OR [c].[Name] IS NULL)) AND (([t].[Name] <> N'Bar') OR [t].[Name] IS NULL)"); } public override async Task Where_contains_on_navigation_with_composite_keys(bool isAsync) @@ -6854,9 +6842,9 @@ SELECT 1 WHERE ([g0].[Discriminator] IN (N'Gear', N'Officer') AND ([c].[Name] = [g0].[CityOrBirthName])) AND (([g0].[Nickname] = [g].[Nickname]) AND ([g0].[SquadId] = [g].[SquadId]))))"); } - public override void Include_with_complex_order_by() + public override async Task Include_with_complex_order_by(bool isAsync) { - base.Include_with_complex_order_by(); + await base.Include_with_complex_order_by(isAsync); AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] @@ -7242,6 +7230,41 @@ SELECT 1 WHERE (([g].[Discriminator] IN (N'Gear', N'Officer') AND ([c].[Name] = [g].[CityOrBirthName])) AND ([g].[Discriminator] = N'Officer')) AND ([g].[Nickname] = N'Marcus'))"); } + public override async Task Query_reusing_parameter_doesnt_declare_duplicate_parameter(bool isAsync) + { + await base.Query_reusing_parameter_doesnt_declare_duplicate_parameter(isAsync); + + AssertSql( + @"@__prm_Inner_Nickname_0='Marcus' (Size = 450) + +SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] +FROM ( + SELECT DISTINCT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + FROM [Gears] AS [g] + WHERE ([g].[Discriminator] IN (N'Gear', N'Officer') AND (([g].[Nickname] <> @__prm_Inner_Nickname_0) OR @__prm_Inner_Nickname_0 IS NULL)) AND (([g].[Nickname] <> @__prm_Inner_Nickname_0) OR @__prm_Inner_Nickname_0 IS NULL) +) AS [t] +ORDER BY [t].[FullName]"); + } + + public override async Task Query_reusing_parameter_doesnt_declare_duplicate_parameter_complex(bool isAsync) + { + await base.Query_reusing_parameter_doesnt_declare_duplicate_parameter_complex(isAsync); + + AssertSql( + @"@__entity_equality_prm_Inner_Squad_0_Id='1' (Nullable = true) + +SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] +FROM ( + SELECT DISTINCT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + FROM [Gears] AS [g] + INNER JOIN [Squads] AS [s] ON [g].[SquadId] = [s].[Id] + WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND (([s].[Id] = @__entity_equality_prm_Inner_Squad_0_Id) AND @__entity_equality_prm_Inner_Squad_0_Id IS NOT NULL) +) AS [t] +INNER JOIN [Squads] AS [s0] ON [t].[SquadId] = [s0].[Id] +WHERE ([s0].[Id] = @__entity_equality_prm_Inner_Squad_0_Id) AND @__entity_equality_prm_Inner_Squad_0_Id IS NOT NULL +ORDER BY [t].[FullName]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.ResultOperators.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.ResultOperators.cs index cba4e0360cd..10d04eaa365 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.ResultOperators.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.ResultOperators.cs @@ -1349,6 +1349,21 @@ public override async Task Sum_over_explicit_cast_over_column(bool isAsync) AssertSql( @"SELECT SUM(CAST([o].[OrderID] AS bigint)) +FROM [Orders] AS [o]"); + } + + public override async Task Count_on_projection_with_client_eval(bool isAsync) + { + await base.Count_on_projection_with_client_eval(isAsync); + + AssertSql( + @"SELECT COUNT(*) +FROM [Orders] AS [o]", + // + @"SELECT COUNT(*) +FROM [Orders] AS [o]", + // + @"SELECT COUNT(*) FROM [Orders] AS [o]"); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs index 6ca501713cc..69577a01227 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs @@ -25,10 +25,10 @@ public override Task Project_collection_navigation_nested_with_take(bool isAsync return base.Project_collection_navigation_nested_with_take(isAsync); } - [ConditionalFact(Skip = "Issue #17230")] - public override void Include_inside_subquery() + [ConditionalTheory(Skip = "Issue #17230")] + public override Task Include_inside_subquery(bool isAsync) { - base.Include_inside_subquery(); + return base.Include_inside_subquery(isAsync); } } }