From 69869ae2fe23ea576ccf9ec8a1f461120dfb0a29 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Fri, 27 Feb 2026 22:42:00 +0000 Subject: [PATCH] Fix #8407 sorting detection on projected EF navigation orderings --- .../QueryableSortContextExtensions.cs | 5 + .../Issue8407ProbeTests.cs | 104 ++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/HotChocolate/Data/test/Data.EntityFramework.Tests/Issue8407ProbeTests.cs diff --git a/src/HotChocolate/Data/src/Data/Sorting/Expressions/Extensions/QueryableSortContextExtensions.cs b/src/HotChocolate/Data/src/Data/Sorting/Expressions/Extensions/QueryableSortContextExtensions.cs index eaaa95ab78b..e37c52104b4 100644 --- a/src/HotChocolate/Data/src/Data/Sorting/Expressions/Extensions/QueryableSortContextExtensions.cs +++ b/src/HotChocolate/Data/src/Data/Sorting/Expressions/Extensions/QueryableSortContextExtensions.cs @@ -79,6 +79,11 @@ protected override Expression VisitMethodCall(MethodCallExpression node) public static bool OrderMethodExists(Expression expression) { + if (!typeof(IOrderedQueryable).IsAssignableFrom(expression.Type)) + { + return false; + } + var visitor = new OrderingMethodFinder(); visitor.Visit(expression); return visitor._orderingMethodFound; diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Tests/Issue8407ProbeTests.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/Issue8407ProbeTests.cs new file mode 100644 index 00000000000..75ccb3851c1 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Tests/Issue8407ProbeTests.cs @@ -0,0 +1,104 @@ +using HotChocolate.Execution; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace HotChocolate.Data; + +public class Issue8407ProbeTests +{ + [Fact] + public async Task Sorting_With_Navigation_OrderBy_In_Projection_Does_Not_Throw() + { + IServiceProvider services = + new ServiceCollection() + .AddDbContextPool( + b => b.UseInMemoryDatabase($"Issue8407-{Guid.NewGuid():N}")) + .AddGraphQL() + .AddSorting() + .AddQueryType() + .Services + .BuildServiceProvider(); + + await using (var scope = services.CreateAsyncScope()) + { + await using var db = scope.ServiceProvider.GetRequiredService(); + + db.Parents.Add( + new Issue8407Parent + { + Id = 2, + Children = + [ + new Issue8407Child { Id = 21, SomeDate = new DateTime(2025, 1, 2) }, + new Issue8407Child { Id = 22, SomeDate = new DateTime(2025, 1, 1) } + ] + }); + + db.Parents.Add( + new Issue8407Parent + { + Id = 1, + Children = + [ + new Issue8407Child { Id = 11, SomeDate = new DateTime(2025, 1, 3) } + ] + }); + + await db.SaveChangesAsync(); + } + + var executor = await services.GetRequiredService() + .GetExecutorAsync(); + + var result = await executor.ExecuteAsync( + """ + { + parents(order: [{ id: ASC }]) { + id + children { + id + } + } + } + """); + + var operationResult = result.ExpectOperationResult(); + Assert.Empty(operationResult.Errors ?? []); + } + + public sealed class Issue8407Query + { + [UseSorting] + public IQueryable GetParents(Issue8407Context db) => + db.Parents + .Select(p => new Issue8407Parent + { + Id = p.Id, + Children = p.Children + .AsQueryable() + .OrderBy(c => c.SomeDate) + .ToList() + }); + } + + public sealed class Issue8407Context(DbContextOptions options) : DbContext(options) + { + public DbSet Parents => Set(); + + public DbSet Children => Set(); + } + + public sealed class Issue8407Parent + { + public int Id { get; set; } + + public List Children { get; set; } = []; + } + + public sealed class Issue8407Child + { + public int Id { get; set; } + + public DateTime SomeDate { get; set; } + } +}