Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,6 @@ dotnet_naming_rule.everything_else_naming.severity = suggestion

# ReSharper properties
resharper_local_function_body = expression_body

# CS9236: Compiling requires binding the lambda expression at least 100 times
dotnet_diagnostic.CS9236.severity = error
Original file line number Diff line number Diff line change
Expand Up @@ -2941,20 +2941,23 @@ public virtual async Task Member_pushdown_chain_3_levels_deep(bool async)
{
using var ctx = CreateContext();

var query = from l1 in ctx.LevelOne
orderby l1.Id
where (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().Name
!= "Foo"
select l1;
#pragma warning disable CS9236 // Compiling requires binding the lambda expression at least 200 times
var query = ctx.LevelOne
.OrderBy(l1 => l1.Id)
.Where(l1 => ctx.LevelTwo
.OrderBy(l2 => l2.Id)
.Where(l2 => l2.Level1_Optional_Id == l1.Id)
.Select(l2 => ctx.LevelThree
.OrderBy(l3 => l3.Id)
.Where(l3 => l3.Level2_Required_Id == l2.Id)
.Select(l3 => ctx.LevelFour
.Where(bool (Level4 l4) => l4.Level3_Required_Id == l3.Id)
.OrderBy(int (Level4 l4) => l4.Id)
.FirstOrDefault())
.FirstOrDefault())
.FirstOrDefault()
.Name != "Foo");
#pragma warning restore CS9236

_ = async ? await query.ToListAsync() : query.ToList();
}
Expand All @@ -2965,18 +2968,20 @@ public virtual async Task Member_pushdown_chain_3_levels_deep_entity(bool async)
{
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 query = ctx.LevelOne
.OrderBy(l1 => l1.Id)
.Select(l1 => ctx.LevelTwo
.OrderBy(l2 => l2.Id)
.Where(l2 => l2.Level1_Optional_Id == l1.Id)
.Select(l2 => ctx.LevelThree
.OrderBy(l3 => l3.Id)
.Where(l3 => l3.Level2_Required_Id == l2.Id)
.Select(l3 => ctx.LevelFour
.Where(bool (Level4 l4) => l4.Level3_Required_Id == l3.Id)
.OrderBy(int (Level4 l4) => l4.Id)
.FirstOrDefault())
.FirstOrDefault())
.FirstOrDefault());

_ = async ? await query.ToListAsync() : query.ToList();
}
Expand Down Expand Up @@ -4052,7 +4057,7 @@ public virtual Task Max_in_multi_level_nested_subquery(bool async)
LevelFour = new
{
xx.OneToOne_Required_FK2.OneToOne_Required_FK3.Id,
Result = (xx.OneToOne_Required_FK2.OneToMany_Optional3.Max(xxx => (int?)xxx.Id) ?? 0)
Result = (xx.OneToOne_Required_FK2.OneToMany_Optional3.Max(int? (Level4 xxx) => (int?)xxx.Id) ?? 0)
> 1
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/EFCore.Specification.Tests/Query/Ef6GroupByTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ public virtual Task Min_Elements_from_LINQ_101(bool async)
ss => from p in ss.Set<ProductForLinq>()
group p by p.Category
into g
let minPrice = g.Min(p => p.UnitPrice)
let minPrice = g.Min(decimal (ProductForLinq p) => p.UnitPrice)
select new { Category = g.Key, CheapestProducts = g.Where(p => p.UnitPrice == minPrice) }));

[ConditionalTheory]
Expand All @@ -383,7 +383,7 @@ public virtual Task Max_Elements_from_LINQ_101(bool async)
ss => from p in ss.Set<ProductForLinq>()
group p by p.Category
into g
let minPrice = g.Max(p => p.UnitPrice)
let minPrice = g.Max(decimal (ProductForLinq p) => p.UnitPrice)
select new { Category = g.Key, MostExpensiveProducts = g.Where(p => p.UnitPrice == minPrice) }));

[ConditionalTheory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,23 +139,23 @@ public virtual Task Sum_over_subquery(bool async)
=> AssertSum(
async,
ss => ss.Set<Customer>(),
selector: c => c.Orders.Sum(o => o.OrderID));
selector: c => c.Orders.Sum(int (Order o) => o.OrderID));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Sum_over_nested_subquery(bool async)
=> AssertSum(
async,
ss => ss.Set<Customer>(),
selector: c => c.Orders.Sum(o => 5 + o.OrderDetails.Sum(od => od.ProductID)));
selector: c => c.Orders.Sum(int (Order o) => 5 + o.OrderDetails.Sum(int (OrderDetail od) => od.ProductID)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Sum_over_min_subquery(bool async)
=> AssertSum(
async,
ss => ss.Set<Customer>(),
selector: c => c.Orders.Sum(o => 5 + o.OrderDetails.Min(od => od.ProductID)));
selector: c => c.Orders.Sum(int (Order o) => 5 + o.OrderDetails.Min(int (OrderDetail od) => od.ProductID)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down Expand Up @@ -270,23 +270,23 @@ public virtual Task Average_over_subquery(bool async)
=> AssertAverage(
async,
ss => ss.Set<Customer>(),
selector: c => c.Orders.Sum(o => o.OrderID));
selector: c => c.Orders.Sum(int (Order o) => o.OrderID));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Average_over_nested_subquery(bool async)
=> AssertAverage(
async,
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
selector: c => (decimal)c.Orders.Average(o => 5 + o.OrderDetails.Average(od => od.ProductID)));
selector: c => (decimal)c.Orders.Average(double (Order o) => 5 + o.OrderDetails.Average(int (OrderDetail od) => od.ProductID)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Average_over_max_subquery(bool async)
=> AssertAverage(
async,
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
selector: c => (decimal)c.Orders.Average(o => 5 + o.OrderDetails.Max(od => od.ProductID)));
selector: c => (decimal)c.Orders.Average(int (Order o) => 5 + o.OrderDetails.Max(int (OrderDetail od) => od.ProductID)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down Expand Up @@ -447,15 +447,15 @@ public virtual Task Min_over_nested_subquery(bool async)
=> AssertMin(
async,
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
selector: c => c.Orders.Min(o => 5 + Enumerable.Min(o.OrderDetails, od => od.ProductID)));
selector: c => c.Orders.Min(o => 5 + Enumerable.Min(o.OrderDetails, int (OrderDetail od) => od.ProductID)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Min_over_max_subquery(bool async)
=> AssertMin(
async,
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
selector: c => c.Orders.Min(o => 5 + o.OrderDetails.Max(od => od.ProductID)));
selector: c => c.Orders.Min(o => 5 + o.OrderDetails.Max(int (OrderDetail od) => od.ProductID)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down Expand Up @@ -494,15 +494,15 @@ public virtual Task Max_over_nested_subquery(bool async)
=> AssertMax(
async,
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
selector: c => c.Orders.Max(o => 5 + Enumerable.Max(o.OrderDetails, od => od.ProductID)));
selector: c => c.Orders.Max(o => 5 + Enumerable.Max(o.OrderDetails, int (OrderDetail od) => od.ProductID)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Max_over_sum_subquery(bool async)
=> AssertMax(
async,
ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(3),
selector: c => c.Orders.Max(o => 5 + o.OrderDetails.Sum(od => od.ProductID)));
selector: c => c.Orders.Max(o => 5 + o.OrderDetails.Sum(int (od) => od.ProductID)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public virtual Task GroupBy_Property_Select_Average_with_group_enumerable_projec
async,
ss => ss.Set<Order>().Where(o => o.Customer.City != "London")
.GroupBy(o => o.CustomerID, (k, es) => new { k, es })
.Select(g => g.es.Average(o => o.OrderID))));
.Select(g => g.es.Average(int (Order o) => o.OrderID))));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down Expand Up @@ -1580,7 +1580,7 @@ into g
{
s.Month,
s.Total,
Payment = ss.Set<Order>().Where(e => e.OrderDate.Value.Month == s.Month).Sum(e => e.OrderID)
Payment = ss.Set<Order>().Where(e => e.OrderDate.Value.Month == s.Month).Sum(int (Order e) => e.OrderID)
},
elementSorter: e => (e.Month, e.Total),
elementAsserter: (e, a) =>
Expand Down Expand Up @@ -1775,7 +1775,7 @@ public virtual Task GroupBy_Aggregate_Join_converted_from_SelectMany(bool async)
ss => from c in ss.Set<Customer>()
from o in ss.Set<Order>().GroupBy(o => o.CustomerID)
.Where(g => g.Count() > 5)
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(o => o.OrderID) })
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(int (Order o) => o.OrderID) })
.Where(c1 => c.CustomerID == c1.CustomerID)
select c);

Expand All @@ -1787,7 +1787,7 @@ public virtual Task GroupBy_Aggregate_LeftJoin_converted_from_SelectMany(bool as
ss => from c in ss.Set<Customer>()
from o in ss.Set<Order>().GroupBy(o => o.CustomerID)
.Where(g => g.Count() > 5)
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(o => o.OrderID) })
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(int (Order o) => o.OrderID) })
.Where(c1 => c.CustomerID == c1.CustomerID)
.DefaultIfEmpty()
select c);
Expand Down Expand Up @@ -2342,7 +2342,7 @@ from oc1 in ss.Set<Order>()
.Where(x => x.CustomerID == c.CustomerID).DefaultIfEmpty()
group new { c.CustomerID, oc1.Count } by c.CustomerID
into g
select new { CustomerID = g.Key, Count = g.Sum(x => x.Count) }).Where(x => x.CustomerID == c1.CustomerID)
select new { CustomerID = g.Key, Count = g.Sum(int? (x) => x.Count) }).Where(x => x.CustomerID == c1.CustomerID)
.DefaultIfEmpty()
select new
{
Expand All @@ -2357,7 +2357,7 @@ from oc1 in ss.Set<Order>()
.Where(x => x.CustomerID == c.CustomerID).DefaultIfEmpty()
group new { c.CustomerID, Count = oc1.MaybeScalar(e => e.Count) } by c.CustomerID
into g
select new { CustomerID = g.Key, Count = g.Sum(x => x.Count) }).Where(x => x.CustomerID == c1.CustomerID)
select new { CustomerID = g.Key, Count = g.Sum(int? (x) => x.Count) }).Where(x => x.CustomerID == c1.CustomerID)
.DefaultIfEmpty()
select new
{
Expand Down Expand Up @@ -3200,7 +3200,7 @@ public virtual Task Complex_query_with_groupBy_in_subquery1(bool async)
Subquery = c.Orders
.Select(o => new { First = o.CustomerID, Second = o.OrderID })
.GroupBy(x => x.First)
.Select(g => new { Sum = g.Sum(x => x.Second) }).ToList()
.Select(g => new { Sum = g.Sum(int (x) => x.Second) }).ToList()
}),
elementSorter: e => e.Key,
elementAsserter: (e, a) =>
Expand All @@ -3222,7 +3222,7 @@ public virtual Task Complex_query_with_groupBy_in_subquery2(bool async)
Subquery = c.Orders
.Select(o => new { First = o.CustomerID, Second = o.OrderID })
.GroupBy(x => x.First)
.Select(g => new { Max = g.Max(x => x.First.Length), Sum = g.Sum(x => x.Second) }).ToList()
.Select(g => new { Max = g.Max(int (x) => x.First.Length), Sum = g.Sum(int (x) => x.Second) }).ToList()
}),
elementSorter: e => e.Key,
elementAsserter: (e, a) =>
Expand All @@ -3244,7 +3244,7 @@ public virtual Task Complex_query_with_groupBy_in_subquery3(bool async)
Subquery = ss.Set<Order>()
.Select(o => new { First = o.CustomerID, Second = o.OrderID })
.GroupBy(x => x.First)
.Select(g => new { Max = g.Max(x => x.First.Length), Sum = g.Sum(x => x.Second) }).ToList()
.Select(g => new { Max = g.Max(int (x) => x.First.Length), Sum = g.Sum(int (x) => x.Second) }).ToList()
}),
elementSorter: e => e.Key,
elementAsserter: (e, a) =>
Expand All @@ -3266,7 +3266,7 @@ public virtual Task Complex_query_with_groupBy_in_subquery4(bool async)
Subquery = c.Orders
.Select(o => new { First = o.OrderID, Second = o.Customer.City + o.CustomerID })
.GroupBy(x => x.Second)
.Select(g => new { Sum = g.Sum(x => x.First), Count = g.Count(x => x.Second.StartsWith("Lon")) }).ToList()
.Select(g => new { Sum = g.Sum(int (x) => x.First), Count = g.Count(x => x.Second.StartsWith("Lon")) }).ToList()
}),
elementSorter: e => e.Key,
elementAsserter: (e, a) =>
Expand All @@ -3288,7 +3288,7 @@ into grouping
{
Sum = grouping.Sum(x => x.ProductID + x.OrderID * 1000),
Subquery = (from c in ss.Set<Customer>()
where c.CustomerID.Length < grouping.Min(x => x.OrderID / 100)
where c.CustomerID.Length < grouping.Min(int (OrderDetail x) => x.OrderID / 100)
orderby c.CustomerID
select new { c.CustomerID, c.City }).ToList()
},
Expand Down Expand Up @@ -3381,7 +3381,7 @@ public virtual Task GroupBy_aggregate_from_multiple_query_in_same_projection_2(b
{
g.Key,
A = ss.Set<Employee>().Where(e => e.City == "Seattle").GroupBy(e => e.City)
.Select(g2 => g2.Count() + g.Min(e => e.OrderID))
.Select(g2 => g2.Count() + g.Min(int (Order e) => e.OrderID))
.OrderBy(e => 1)
.FirstOrDefault()
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ public virtual Task GroupJoin_aggregate_nested_anonymous_key_selectors(bool asyn
ss.Set<Order>(),
x => new { x.CustomerID, Nested = new { x.City, Year = 1996 } },
x => new { x.CustomerID, Nested = new { City = "London", x.OrderDate.Value.Year } },
(c, g) => new { c.CustomerID, Sum = g.Sum(x => x.CustomerID.Length) }),
(c, g) => new { c.CustomerID, Sum = g.Sum(int (x) => x.CustomerID.Length) }),
elementSorter: e => e.CustomerID));

[ConditionalTheory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,7 @@ public virtual Task Where_query_composition3(bool async)
where c1.City == ss.Set<Customer>().OrderBy(c => c.CustomerID).First(c => c.IsLondon).City
select c1));

#pragma warning disable CS9236 // Compiling requires binding the lambda expression at least 200 times
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/cc @jaredpar @CyrusNajmabadi

Here I got a CS9236, but oddly adding the typing information didn't make it go away (SDK 10.0.100-preview.6.25358.103). A naive attempt at a minimal repro didn't work (see code below). Let me know if there are known false positives like this or how I can help.

Failed attempted repro
await using var context = new CustomerContext();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();

await AssertTranslationFailed(
    () => AssertQuery(
        async: true,
        ss => from c1 in ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(2)
                where c1.City
                    == (from c2 in ss.Set<Customer>().OrderBy(c => c.CustomerID)
                        // from c3 in ss.Set<Customer>().OrderBy(bool (Customer c) => c.IsLondon).ThenBy(string (Customer c) => c.CustomerID)
                        from c3 in ss.Set<Customer>().OrderBy(c => c.IsLondon).ThenBy(string (Customer c) => c.CustomerID)
                        select new { c3 }).First().c3.City
                select c1));

static Task AssertTranslationFailed(Func<Task> query)
    => throw new NotImplementedException();

Task AssertQuery<TResult>(
        bool async,
        Func<CustomerContext, IQueryable<TResult>> query,
        Func<TResult, object>? elementSorter = null,
        Action<TResult, TResult>? elementAsserter = null,
        bool assertOrder = false,
        bool assertEmpty = false,
        QueryTrackingBehavior? queryTrackingBehavior = null,
        [CallerMemberName] string testMethodName = "")
        => throw new NotImplementedException();

public class CustomerContext : DbContext;

public class Customer
{
    public required string CustomerID { get; set; }
    public required string City { get; set; }
    public bool IsLondon { get; set; }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's possible the outer from/where and the selects are themselves the ones having issues. you may have to write this without linq entirely.

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Where_query_composition4(bool async)
Expand All @@ -1842,9 +1843,10 @@ public virtual Task Where_query_composition4(bool async)
ss => from c1 in ss.Set<Customer>().OrderBy(c => c.CustomerID).Take(2)
where c1.City
== (from c2 in ss.Set<Customer>().OrderBy(c => c.CustomerID)
from c3 in ss.Set<Customer>().OrderBy(c => c.IsLondon).ThenBy(c => c.CustomerID)
from c3 in ss.Set<Customer>().OrderBy(bool (Customer c) => c.IsLondon).ThenBy(string (Customer c) => c.CustomerID)
select new { c3 }).First().c3.City
select c1));
#pragma warning restore CS9236

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down Expand Up @@ -3990,6 +3992,7 @@ public virtual Task Complex_query_with_repeated_query_model_compiles_correctly(b
where customers.Any()
select customers).Any()));

#pragma warning disable CS9236 // Compiling requires binding the lambda expression at least 200 times
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Complex_query_with_repeated_nested_query_model_compiles_correctly(bool async)
Expand All @@ -4001,10 +4004,11 @@ public virtual Task Complex_query_with_repeated_nested_query_model_compiles_corr
outer =>
(from c in ss.Set<Customer>()
let customers = ss.Set<Customer>().Where(
cc => ss.Set<Customer>().OrderBy(inner => inner.CustomerID).Take(10).Distinct().Any())
cc => ss.Set<Customer>().OrderBy(string (Customer inner) => inner.CustomerID).Take(10).Distinct().Any())
.Select(cc => cc.CustomerID).ToList()
where customers.Any()
select customers).Any()));
#pragma warning restore CS9236

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down
Loading