diff --git a/Versions.props b/Versions.props index 9cd719d4..165b456f 100644 --- a/Versions.props +++ b/Versions.props @@ -4,7 +4,7 @@ 9.0.16 10.0.8 - 3.9.0 + 3.10.0 $(DRIVER_VERSION) diff --git a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindJoinQueryMongoTest.cs b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindJoinQueryMongoTest.cs index f16e3ae9..1c3b8a41 100644 --- a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindJoinQueryMongoTest.cs +++ b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindJoinQueryMongoTest.cs @@ -148,87 +148,43 @@ public override async Task Join_customers_orders_select(bool async) public override async Task Join_customers_orders_with_subquery(bool async) { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Join_customers_orders_with_subquery(async))).Message); + await base.Join_customers_orders_with_subquery(async); AssertMql( """ -Customers. +Customers.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Orders", "localField" : "_outer._id", "foreignField" : "CustomerID", "pipeline" : [{ "$sort" : { "_id" : 1 } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "Outer" : "$_outer", "Inner" : "$_inner", "_id" : 0 } }, { "$match" : { "Inner.CustomerID" : "ALFKI" } }, { "$project" : { "ContactName" : "$Outer.ContactName", "OrderID" : "$Inner._id", "_id" : 0 } } """); } + [ConditionalTheory(Skip = "CSHARP-6017: driver 3.10 folds an uncorrelated Take/subquery join inner into the correlated $lookup sub-pipeline, returning wrong results")] + [MemberData(nameof(IsAsyncData))] public override async Task Join_customers_orders_with_subquery_with_take(bool async) - { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Join_customers_orders_with_subquery_with_take(async))).Message); - - AssertMql( - """ -Customers. -"""); - } + => await base.Join_customers_orders_with_subquery_with_take(async); + [ConditionalTheory(Skip = "EF-352: shadow property read via EF.Property in a client-side join projection materialises as null")] + [MemberData(nameof(IsAsyncData))] public override async Task Join_customers_orders_with_subquery_anonymous_property_method(bool async) - { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Join_customers_orders_with_subquery_anonymous_property_method(async))).Message); - - AssertMql( - """ -Customers. -"""); - } + => await base.Join_customers_orders_with_subquery_anonymous_property_method(async); + [ConditionalTheory(Skip = "CSHARP-6017: driver 3.10 folds an uncorrelated Take/subquery join inner into the correlated $lookup sub-pipeline, returning wrong results")] + [MemberData(nameof(IsAsyncData))] public override async Task Join_customers_orders_with_subquery_anonymous_property_method_with_take(bool async) - { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Join_customers_orders_with_subquery_anonymous_property_method_with_take(async))).Message); - - AssertMql( - """ -Customers. -"""); - } + => await base.Join_customers_orders_with_subquery_anonymous_property_method_with_take(async); public override async Task Join_customers_orders_with_subquery_predicate(bool async) { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Join_customers_orders_with_subquery_predicate(async))).Message); + await base.Join_customers_orders_with_subquery_predicate(async); AssertMql( """ -Customers. +Customers.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Orders", "localField" : "_outer._id", "foreignField" : "CustomerID", "pipeline" : [{ "$match" : { "_id" : { "$gt" : 0 } } }, { "$sort" : { "_id" : 1 } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "Outer" : "$_outer", "Inner" : "$_inner", "_id" : 0 } }, { "$match" : { "Inner.CustomerID" : "ALFKI" } }, { "$project" : { "ContactName" : "$Outer.ContactName", "OrderID" : "$Inner._id", "_id" : 0 } } """); } + [ConditionalTheory(Skip = "CSHARP-6017: driver 3.10 folds an uncorrelated Take/subquery join inner into the correlated $lookup sub-pipeline, returning wrong results")] + [MemberData(nameof(IsAsyncData))] public override async Task Join_customers_orders_with_subquery_predicate_with_take(bool async) - { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Join_customers_orders_with_subquery_predicate_with_take(async))).Message); - - AssertMql( - """ -Customers. -"""); - } + => await base.Join_customers_orders_with_subquery_predicate_with_take(async); public override async Task Join_composite_key(bool async) { @@ -316,19 +272,10 @@ public override async Task GroupJoin_simple_ordering(bool async) """); } + [ConditionalTheory(Skip = "CSHARP-6017: driver 3.10 folds an uncorrelated Take/subquery join inner into the correlated $lookup sub-pipeline, returning wrong results")] + [MemberData(nameof(IsAsyncData))] public override async Task GroupJoin_simple_subquery(bool async) - { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.GroupJoin_simple_subquery(async))).Message); - - AssertMql( - """ -Customers. -"""); - } + => await base.GroupJoin_simple_subquery(async); public override async Task GroupJoin_as_final_operator(bool async) { @@ -402,14 +349,11 @@ public override async Task GroupJoin_DefaultIfEmpty2(bool async) AssertMql( ); #else - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.GroupJoin_DefaultIfEmpty2(async))).Message); + await base.GroupJoin_DefaultIfEmpty2(async); AssertMql( """ -Employees. +Employees.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Orders", "localField" : "_outer._id", "foreignField" : "EmployeeID", "pipeline" : [{ "$match" : { "CustomerID" : { "$regularExpression" : { "pattern" : "^F", "options" : "s" } } } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "_outer" : "$_outer", "_inner" : "$_inner", "_id" : 0 } } """); #endif } @@ -499,15 +443,11 @@ public override async Task GroupJoin_DefaultIfEmpty_Project(bool async) public override async Task GroupJoin_SelectMany_subquery_with_filter(bool async) { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.GroupJoin_SelectMany_subquery_with_filter(async))).Message); + await base.GroupJoin_SelectMany_subquery_with_filter(async); AssertMql( """ -Customers. +Customers.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Orders", "localField" : "_outer._id", "foreignField" : "CustomerID", "pipeline" : [{ "$match" : { "_id" : { "$gt" : 5 } } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "Outer" : "$_outer", "Inner" : "$_inner", "_id" : 0 } }, { "$project" : { "ContactName" : "$Outer.ContactName", "OrderID" : "$Inner._id", "_id" : 0 } } """); } @@ -533,7 +473,7 @@ public override async Task GroupJoin_SelectMany_subquery_with_filter_and_Default AssertMql( """ -Customers. +Customers.{ "$match" : { "_id" : { "$regularExpression" : { "pattern" : "^F", "options" : "s" } } } }, { "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Orders", "localField" : "_outer._id", "foreignField" : "CustomerID", "pipeline" : [{ "$match" : { "_id" : { "$gt" : 5 } } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "_outer" : "$_outer", "_inner" : "$_inner", "_id" : 0 } } """); #endif } @@ -546,19 +486,10 @@ public override async Task GroupJoin_SelectMany_subquery_with_filter_orderby_and ); } + [ConditionalTheory(Skip = "CSHARP-6017: driver 3.10 folds an uncorrelated Take/subquery join inner into the correlated $lookup sub-pipeline, returning wrong results")] + [MemberData(nameof(IsAsyncData))] public override async Task GroupJoin_Subquery_with_Take_Then_SelectMany_Where(bool async) - { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.GroupJoin_Subquery_with_Take_Then_SelectMany_Where(async))).Message); - - AssertMql( - """ -Customers. -"""); - } + => await base.GroupJoin_Subquery_with_Take_Then_SelectMany_Where(async); public override async Task Inner_join_with_tautology_predicate_converts_to_cross_join(bool async) { @@ -759,31 +690,18 @@ public override async Task GroupJoin_customers_employees_shadow(bool async) public override async Task GroupJoin_customers_employees_subquery_shadow(bool async) { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.GroupJoin_customers_employees_subquery_shadow(async))).Message); + await base.GroupJoin_customers_employees_subquery_shadow(async); AssertMql( """ -Customers. +Customers.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Employees", "localField" : "_outer.City", "foreignField" : "City", "pipeline" : [{ "$sort" : { "City" : 1 } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "Outer" : "$_outer", "Inner" : "$_inner", "_id" : 0 } }, { "$project" : { "Title" : "$Inner.Title", "_id" : "$Inner._id" } } """); } + [ConditionalTheory(Skip = "CSHARP-6017: driver 3.10 folds an uncorrelated Take/subquery join inner into the correlated $lookup sub-pipeline, returning wrong results")] + [MemberData(nameof(IsAsyncData))] public override async Task GroupJoin_customers_employees_subquery_shadow_take(bool async) - { - // Fails: Subquery selection EF-X001 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.GroupJoin_customers_employees_subquery_shadow_take(async))).Message); - - AssertMql( - """ -Customers. -"""); - } + => await base.GroupJoin_customers_employees_subquery_shadow_take(async); public override async Task GroupJoin_projection(bool async) { diff --git a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindMiscellaneousQueryMongoTest.cs b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindMiscellaneousQueryMongoTest.cs index 517b02e8..effff729 100644 --- a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindMiscellaneousQueryMongoTest.cs +++ b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindMiscellaneousQueryMongoTest.cs @@ -3412,10 +3412,7 @@ public override async Task Comparing_collection_navigation_to_null_complex(bool AssertMql( ); #else - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Comparing_collection_navigation_to_null_complex(async))).Message); + await Assert.ThrowsAnyAsync(() => base.Comparing_collection_navigation_to_null_complex(async)); AssertMql( """ @@ -3517,15 +3514,11 @@ public override async Task OrderBy_Dto_projection_skip_take(bool async) public override async Task Join_take_count_works(bool async) { - // Fails: Cross-document navigation access issue EF-216 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Join_take_count_works(async))).Message); + await base.Join_take_count_works(async); AssertMql( """ -Orders. +Orders.{ "$match" : { "_id" : { "$gt" : 690, "$lt" : 710 } } }, { "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Customers", "localField" : "_outer.CustomerID", "foreignField" : "_id", "pipeline" : [{ "$match" : { "_id" : "ALFKI" } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "Outer" : "$_outer", "Inner" : "$_inner", "_id" : 0 } }, { "$limit" : 5 }, { "$count" : "_v" } """); } @@ -3793,16 +3786,12 @@ public override async Task Anonymous_projection_skip_take_empty_collection_First public override async Task Checked_context_with_arithmetic_does_not_fail(bool async) { - // Fails: checked issue EF-249 - Assert.Contains( - "Expression not supported: (ConvertChecked", - (await Assert.ThrowsAsync(() => - base.Checked_context_with_arithmetic_does_not_fail(async))).Message); + await base.Checked_context_with_arithmetic_does_not_fail(async); AssertMql( """ - OrderDetails. - """); +OrderDetails.{ "$match" : { "$and" : [{ "$expr" : { "$eq" : [{ "$add" : [{ "$toInt" : "$Quantity" }, 1] }, 5] } }, { "$expr" : { "$eq" : [{ "$subtract" : [{ "$toInt" : "$Quantity" }, 1] }, 3] } }, { "$expr" : { "$eq" : [{ "$multiply" : [{ "$toInt" : "$Quantity" }, 1] }, { "$toInt" : "$Quantity" }] } }] } }, { "$sort" : { "_id.OrderID" : 1 } } +"""); } public override async Task Checked_context_with_case_to_same_nullable_type_does_not_fail(bool isAsync) @@ -4174,15 +4163,11 @@ public override async Task Max_on_empty_sequence_throws(bool async) public override async Task OrderBy_Join(bool async) { - // Fails: Cross-document navigation access issue EF-216 - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.OrderBy_Join(async))).Message); + await base.OrderBy_Join(async); AssertMql( """ -Customers. +Customers.{ "$sort" : { "_id" : 1 } }, { "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Orders", "localField" : "_outer._id", "foreignField" : "CustomerID", "pipeline" : [{ "$sort" : { "_id" : 1 } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "Outer" : "$_outer", "Inner" : "$_inner", "_id" : 0 } }, { "$project" : { "CustomerID" : "$Outer._id", "OrderID" : "$Inner._id", "_id" : 0 } } """); } diff --git a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindNavigationsQueryMongoTest.cs b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindNavigationsQueryMongoTest.cs index da8a8445..ce4839c7 100644 --- a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindNavigationsQueryMongoTest.cs +++ b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindNavigationsQueryMongoTest.cs @@ -76,14 +76,11 @@ public override async Task Select_Where_Navigation_Deep(bool async) AssertMql( ); #else - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Select_Where_Navigation_Deep(async))).Message); + await Assert.ThrowsAnyAsync(() => base.Select_Where_Navigation_Deep(async)); AssertMql( """ -OrderDetails. +OrderDetails.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Orders", "localField" : "_outer._id.OrderID", "foreignField" : "_id", "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "Outer" : "$_outer", "Inner" : "$_inner", "_id" : 0 } }, { "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Customers", "localField" : "_outer.Inner.CustomerID", "foreignField" : "_id", "as" : "_inner" } }, { "$unwind" : { "path" : "$_inner", "preserveNullAndEmptyArrays" : true } }, { "$project" : { "Outer" : "$_outer", "Inner" : "$_inner", "_id" : 0 } }, { "$match" : { "Inner.City" : "Seattle" } }, { "$sort" : { "Outer.Outer._id.OrderID" : 1, "Outer.Outer._id.ProductID" : 1 } }, { "$limit" : 1 }, { "$project" : { "_v" : "$Outer.Outer", "_id" : 0 } } """); #endif } diff --git a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindQueryFiltersQueryMongoTest.cs b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindQueryFiltersQueryMongoTest.cs index 50bc3080..7c5d1c62 100644 --- a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindQueryFiltersQueryMongoTest.cs +++ b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindQueryFiltersQueryMongoTest.cs @@ -137,11 +137,11 @@ public override async Task Included_many_to_one_query(bool async) AssertMql( ); #else - await Assert.ThrowsAnyAsync(() => base.Included_many_to_one_query(async)); + await base.Included_many_to_one_query(async); AssertMql( """ -Orders. +Orders.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Customers", "localField" : "_outer.CustomerID", "foreignField" : "_id", "pipeline" : [{ "$match" : { "CompanyName" : { "$regularExpression" : { "pattern" : "^B", "options" : "s" } } } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "_outer" : "$_outer", "_inner" : "$_inner", "_id" : 0 } }, { "$match" : { "_inner" : { "$ne" : null }, "_inner.CompanyName" : { "$ne" : null } } } """); #endif } @@ -197,14 +197,11 @@ public override async Task Entity_Equality(bool async) AssertMql( ); #else - Assert.Contains( - "Expression not supported", - (await Assert.ThrowsAsync(() => - base.Entity_Equality(async))).Message); + await base.Entity_Equality(async); AssertMql( """ -Orders. +Orders.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Customers", "localField" : "_outer.CustomerID", "foreignField" : "_id", "pipeline" : [{ "$match" : { "CompanyName" : { "$regularExpression" : { "pattern" : "^B", "options" : "s" } } } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "_outer" : "$_outer", "_inner" : "$_inner", "_id" : 0 } }, { "$match" : { "_inner" : { "$ne" : null }, "_inner.CompanyName" : { "$ne" : null } } } """); #endif } @@ -231,11 +228,11 @@ public override async Task Included_many_to_one_query2(bool async) AssertMql( ); #else - await Assert.ThrowsAnyAsync(() => base.Included_many_to_one_query2(async)); + await base.Included_many_to_one_query2(async); AssertMql( """ -Orders. +Orders.{ "$project" : { "_outer" : "$$ROOT", "_id" : 0 } }, { "$lookup" : { "from" : "Customers", "localField" : "_outer.CustomerID", "foreignField" : "_id", "pipeline" : [{ "$match" : { "CompanyName" : { "$regularExpression" : { "pattern" : "^B", "options" : "s" } } } }], "as" : "_inner" } }, { "$unwind" : "$_inner" }, { "$project" : { "_outer" : "$_outer", "_inner" : "$_inner", "_id" : 0 } }, { "$match" : { "_inner" : { "$ne" : null }, "_inner.CompanyName" : { "$ne" : null } } } """); #endif } diff --git a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindWhereQueryMongoTest.cs b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindWhereQueryMongoTest.cs index 3f194138..e5d518b8 100644 --- a/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindWhereQueryMongoTest.cs +++ b/tests/MongoDB.EntityFrameworkCore.SpecificationTests/Query/NorthwindWhereQueryMongoTest.cs @@ -504,19 +504,10 @@ public override async Task Where_equals_method_int(bool async) """); } + [ConditionalTheory(Skip = "CSHARP-6126: driver 3.10 translates mismatched-type equality to a value match, returning rows where .NET object-equality returns none")] + [MemberData(nameof(IsAsyncData))] public override async Task Where_equals_using_object_overload_on_mismatched_types(bool async) - { - // Fails: Equals with different types issue EF-221 - Assert.Contains( - "Unable to cast object of type 'System.UInt64' to type 'System.UInt32'.", - (await Assert.ThrowsAsync(() => - base.Where_equals_using_object_overload_on_mismatched_types(async))).Message); - - AssertMql( - """ - Employees. - """); - } + => await base.Where_equals_using_object_overload_on_mismatched_types(async); public override async Task Where_equals_using_int_overload_on_mismatched_types(bool async) { @@ -528,19 +519,10 @@ public override async Task Where_equals_using_int_overload_on_mismatched_types(b """); } + [ConditionalTheory(Skip = "CSHARP-6126: driver 3.10 translates mismatched-type equality to a value match, returning rows where .NET object-equality returns none")] + [MemberData(nameof(IsAsyncData))] public override async Task Where_equals_on_mismatched_types_nullable_int_long(bool async) - { - // Fails: Equals with different types issue EF-221 - Assert.Contains( - "Unable to cast object of type 'System.UInt64' to type 'System.Nullable`1[System.UInt32]'.", - (await Assert.ThrowsAsync(() => base.Where_equals_on_mismatched_types_nullable_int_long(async))) - .Message); - - AssertMql( - """ - Employees. - """); - } + => await base.Where_equals_on_mismatched_types_nullable_int_long(async); public override async Task Where_equals_on_mismatched_types_nullable_long_nullable_int(bool async) {