diff --git a/src/HotChocolate/Data/src/EntityFramework/Pagination/EfQueryableCursorPagingHandler.cs b/src/HotChocolate/Data/src/EntityFramework/Pagination/EfQueryableCursorPagingHandler.cs index e15e027f651..bdcb80b4eb5 100644 --- a/src/HotChocolate/Data/src/EntityFramework/Pagination/EfQueryableCursorPagingHandler.cs +++ b/src/HotChocolate/Data/src/EntityFramework/Pagination/EfQueryableCursorPagingHandler.cs @@ -45,13 +45,13 @@ private async ValueTask SliceAsync( if (arguments.After is not null) { var cursor = CursorParser.Parse(arguments.After, keys); - query = query.Where(ExpressionHelpers.BuildWhereExpression(keys, cursor, forward)); + query = query.Where(ExpressionHelpers.BuildWhereExpression(keys, cursor, true)); } if (arguments.Before is not null) { var cursor = CursorParser.Parse(arguments.Before, keys); - query = query.Where(ExpressionHelpers.BuildWhereExpression(keys, cursor, forward)); + query = query.Where(ExpressionHelpers.BuildWhereExpression(keys, cursor, false)); } if (arguments.First is not null) diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/IntegrationTests.cs b/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/IntegrationTests.cs index a236f7fb47c..f4bd8261252 100644 --- a/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/IntegrationTests.cs +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/IntegrationTests.cs @@ -316,6 +316,78 @@ public async Task Paging_Last_10_With_Default_Sorting_HasPreviousPage() result.MatchMarkdownSnapshot(); } + [Fact] + public async Task Paging_Fetch_First_2_Items_Between() + { + var connectionString = CreateConnectionString(); + await SeedAsync(connectionString); + + var executor = await new ServiceCollection() + .AddScoped(_ => new CatalogContext(connectionString)) + .AddGraphQLServer() + .AddQueryType() + .AddSorting() + .AddDbContextCursorPagingProvider() + .BuildRequestExecutorAsync(); + + var result = await executor.ExecuteAsync(q => q + .SetDocument( + """ + { + brands(first: 2, after:"MQ==", before:"NA==") { + nodes { + name + } + pageInfo { + hasNextPage + hasPreviousPage + endCursor + startCursor + } + } + } + """) + .SetGlobalState("printSQL", true)); + + result.MatchMarkdownSnapshot(); + } + + [Fact] + public async Task Paging_Fetch_Last_2_Items_Between() + { + var connectionString = CreateConnectionString(); + await SeedAsync(connectionString); + + var executor = await new ServiceCollection() + .AddScoped(_ => new CatalogContext(connectionString)) + .AddGraphQLServer() + .AddQueryType() + .AddSorting() + .AddDbContextCursorPagingProvider() + .BuildRequestExecutorAsync(); + + var result = await executor.ExecuteAsync(q => q + .SetDocument( + """ + { + brands(last: 2, after:"OTc=", before:"MTAw") { + nodes { + name + } + pageInfo { + hasNextPage + hasPreviousPage + endCursor + startCursor + } + } + } + """) + .SetGlobalState("printSQL", true)); + + result.MatchMarkdownSnapshot(); + } + public class Query { [UsePaging] diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/__snapshots__/IntegrationTests.Paging_Fetch_First_2_Items_Between.md b/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/__snapshots__/IntegrationTests.Paging_Fetch_First_2_Items_Between.md new file mode 100644 index 00000000000..4c7aa752c04 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/__snapshots__/IntegrationTests.Paging_Fetch_First_2_Items_Between.md @@ -0,0 +1,27 @@ +# Paging_Fetch_First_2_Items_Between + +```json +{ + "data": { + "brands": { + "nodes": [ + { + "name": "Brand1" + }, + { + "name": "Brand2" + } + ], + "pageInfo": { + "hasNextPage": true, + "hasPreviousPage": true, + "endCursor": "Mw==", + "startCursor": "Mg==" + } + } + }, + "extensions": { + "sql": "-- @__p_0='1'\n-- @__p_1='4'\n-- @__p_2='3'\nSELECT b.\"Id\", b.\"AlwaysNull\", b.\"DisplayName\", b.\"Name\", b.\"BrandDetails_Country_Name\"\nFROM \"Brands\" AS b\nWHERE b.\"Id\" > @__p_0 AND b.\"Id\" < @__p_1\nORDER BY b.\"Id\"\nLIMIT @__p_2" + } +} +``` diff --git a/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/__snapshots__/IntegrationTests.Paging_Fetch_Last_2_Items_Between.md b/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/__snapshots__/IntegrationTests.Paging_Fetch_Last_2_Items_Between.md new file mode 100644 index 00000000000..ba4bc537766 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.EntityFramework.Pagination.Tests/__snapshots__/IntegrationTests.Paging_Fetch_Last_2_Items_Between.md @@ -0,0 +1,27 @@ +# Paging_Fetch_Last_2_Items_Between + +```json +{ + "data": { + "brands": { + "nodes": [ + { + "name": "Brand97" + }, + { + "name": "Brand98" + } + ], + "pageInfo": { + "hasNextPage": true, + "hasPreviousPage": true, + "endCursor": "OTk=", + "startCursor": "OTg=" + } + } + }, + "extensions": { + "sql": "-- @__p_0='97'\n-- @__p_1='100'\n-- @__p_2='3'\nSELECT b.\"Id\", b.\"AlwaysNull\", b.\"DisplayName\", b.\"Name\", b.\"BrandDetails_Country_Name\"\nFROM \"Brands\" AS b\nWHERE b.\"Id\" > @__p_0 AND b.\"Id\" < @__p_1\nORDER BY b.\"Id\" DESC\nLIMIT @__p_2" + } +} +```