question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SelectMany subquery not applying OrderBy

See original GitHub issue

Applying an OrderBy to a subquery in a SelectMany statement does not appear to work unless either a skip or take call is applied as well.

Database Structure

public class AppDbContext : DbContext
{
	public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
	{
	}

	public DbSet<Thread> Threads { get; set; }
	public DbSet<Post> Posts { get; set; }
}

public class Thread
{
	public Guid Id { get; set; }
	public ICollection<Post> Posts { get; set; }
}

public class Post 
{
	public Guid Id { get; set; }
	public string Message { get; set; }
	public Guid ThreadId { get; set; }
	public Thread Thread { get; set; }
}

Query

This query will produce the following SQL.

using var dbContext = new AppDbContext(dbOptions.Options);
var query = dbContext.Posts;
var data = query
	.Select(x => x.ThreadId)
	.Distinct()
	.SelectMany(x => query
		.Where(y => y.ThreadId == x)
		.OrderBy(y => y.Message))
	.ToList();

Will make

SELECT "t0"."Id", "t0"."Message", "t0"."ThreadId"
FROM (
	SELECT DISTINCT "p"."ThreadId"
	FROM "Posts" AS "p"
) AS "t"
INNER JOIN (
	SELECT "p0"."Id", "p0"."Message", "p0"."ThreadId"
	FROM "Posts" AS "p0"
) AS "t0" ON "t"."ThreadId" = "t0"."ThreadId"

You can see that there is no ORDER BY added to the generated SQL, However if I add a .Skip(0) to the subquery then an order by is generated in the sql.

using var dbContext = new AppDbContext(dbOptions.Options);
var query = dbContext.Posts;
var data = query
	.Select(x => x.ThreadId)
	.Distinct()
	.SelectMany(x => query
		.Where(y => y.ThreadId == x)
		.OrderBy(y => y.Message)
		.Skip(0))
	.ToList();

Will make

SELECT "t1"."Id", "t1"."Message", "t1"."ThreadId"
FROM (
	SELECT DISTINCT "p"."ThreadId"
	FROM "Posts" AS "p"
) AS "t"
INNER JOIN (
	SELECT "t0"."Id", "t0"."Message", "t0"."ThreadId"
	FROM (
		SELECT "p0"."Id", "p0"."Message", "p0"."ThreadId", ROW_NUMBER() OVER(PARTITION BY "p0"."ThreadId" ORDER BY "p0"."Message") AS "row"
		FROM "Posts" AS "p0"
	) AS "t0"
	WHERE 0 < "t0"."row"
) AS "t1" ON "t"."ThreadId" = "t1"."ThreadId"

We can see that now the order by over the partitions is working correctly. I have also observed that if there is a Take on the subquery instead of a Skip then it will also add the order by to the sql correctly as well.

Version Info

EF Core version: Database provider: Have observed in both Microsoft.EntityFrameworkCore.Sqlite 5.0.5 and Npgsql.EntityFrameworkCore.PostgreSQL 5.0.2 Target framework: .NET 5.0 Operating system: Windows 10, Ubuntu 20.04 IDE: Rider, VS Code

Full example project here: https://github.com/jack775544/EfOrder

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
smitpatelcommented, Apr 20, 2021

ORDER BY lifting specification from the past (EF6 & LINQ-to-SQL) also explicitly noted that the ordering from right side of a join cannot be lifted.

1reaction
smitpatelcommented, Apr 19, 2021
Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - Subquery, inside Select, not applying Order By to ...
Looks like you've hit (one of the few compared to EF Core) EF6 query translation bug since the generated SQL query has no...
Read more >
Why is ORDER BY in a FROM Subquery Ignored?
This totally screws up previously working code that attempts to group based on the results of the ordered subquery. You cannot sort before...
Read more >
Database Implementations of ORDER BY in a Subquery
You're going to have to make your application not put the ORDER BY inside the subquery (maybe it has an option to not...
Read more >
Complex Query Operators - EF Core
Join; GroupJoin; SelectMany; GroupBy; Left Join ... Not all LINQ operators have suitable translations on the server side.
Read more >
ORDER BY
ORDER BY ¶. Specifies an ordering of the rows of the result table from a SELECT list. ... The ORDER BY in the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found