From a11ea26a0ac6a725c2875b56fe7448cef972149d Mon Sep 17 00:00:00 2001 From: "m.haynie" Date: Tue, 23 Dec 2025 14:46:55 +0100 Subject: [PATCH] Only querying total count when IncludeTotalResourceCount is true but pagination is disabled --- .../Services/JsonApiResourceService.cs | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs b/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs index de5d3b7b1f..1971917c40 100644 --- a/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs +++ b/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs @@ -62,7 +62,10 @@ public virtual async Task> GetAsync(CancellationT using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get resources"); - if (_options.IncludeTotalResourceCount) + QueryLayer queryLayer = _queryLayerComposer.ComposeFromConstraints(_request.PrimaryResourceType); + bool isPaginationDisabled = queryLayer.Pagination?.PageSize == null; + + if (_options.IncludeTotalResourceCount && !isPaginationDisabled) { FilterExpression? topFilter = _queryLayerComposer.GetPrimaryFilterFromConstraints(_request.PrimaryResourceType); _paginationContext.TotalResourceCount = await _repositoryAccessor.CountAsync(_request.PrimaryResourceType, topFilter, cancellationToken); @@ -73,7 +76,6 @@ public virtual async Task> GetAsync(CancellationT } } - QueryLayer queryLayer = _queryLayerComposer.ComposeFromConstraints(_request.PrimaryResourceType); IReadOnlyCollection resources = await _repositoryAccessor.GetAsync(queryLayer, cancellationToken); if (queryLayer.Pagination?.PageSize?.Value == resources.Count) @@ -81,6 +83,11 @@ public virtual async Task> GetAsync(CancellationT _paginationContext.IsPageFull = true; } + if (_options.IncludeTotalResourceCount && _paginationContext.TotalResourceCount == null) + { + _paginationContext.TotalResourceCount = resources.Count; + } + return resources; } @@ -112,7 +119,10 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get secondary resource(s)"); - if (_options.IncludeTotalResourceCount && _request.IsCollection) + QueryLayer secondaryLayer = _queryLayerComposer.ComposeFromConstraints(_request.SecondaryResourceType!); + bool isPaginationDisabled = secondaryLayer.Pagination?.PageSize == null; + + if (_options.IncludeTotalResourceCount && !isPaginationDisabled) { await RetrieveResourceCountForNonPrimaryEndpointAsync(id, (HasManyAttribute)_request.Relationship, cancellationToken); @@ -120,7 +130,6 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio // the parent resource exists. In case the parent does not exist, an error is produced below. } - QueryLayer secondaryLayer = _queryLayerComposer.ComposeFromConstraints(_request.SecondaryResourceType!); QueryLayer primaryLayer = _queryLayerComposer.WrapLayerForSecondaryEndpoint(secondaryLayer, _request.PrimaryResourceType, id, _request.Relationship); IReadOnlyCollection primaryResources = await _repositoryAccessor.GetAsync(primaryLayer, cancellationToken); @@ -134,6 +143,11 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio _paginationContext.IsPageFull = true; } + if (_options.IncludeTotalResourceCount && _paginationContext.TotalResourceCount == null && rightValue is ICollection rightResourcesForCount) + { + _paginationContext.TotalResourceCount = rightResourcesForCount.Count; + } + return rightValue; } @@ -152,7 +166,10 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio using IDisposable _ = CodeTimingSessionManager.Current.Measure("Service - Get relationship"); - if (_options.IncludeTotalResourceCount && _request.IsCollection) + QueryLayer secondaryLayer = _queryLayerComposer.ComposeSecondaryLayerForRelationship(_request.SecondaryResourceType!); + bool isPaginationDisabled = secondaryLayer.Pagination?.PageSize == null; + + if (_options.IncludeTotalResourceCount && !isPaginationDisabled) { await RetrieveResourceCountForNonPrimaryEndpointAsync(id, (HasManyAttribute)_request.Relationship, cancellationToken); @@ -160,7 +177,6 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio // the parent resource exists. In case the parent does not exist, an error is produced below. } - QueryLayer secondaryLayer = _queryLayerComposer.ComposeSecondaryLayerForRelationship(_request.SecondaryResourceType!); QueryLayer primaryLayer = _queryLayerComposer.WrapLayerForSecondaryEndpoint(secondaryLayer, _request.PrimaryResourceType, id, _request.Relationship); IReadOnlyCollection primaryResources = await _repositoryAccessor.GetAsync(primaryLayer, cancellationToken); @@ -174,6 +190,11 @@ public virtual async Task GetAsync([DisallowNull] TId id, Cancellatio _paginationContext.IsPageFull = true; } + if (_options.IncludeTotalResourceCount && _paginationContext.TotalResourceCount == null && rightValue is ICollection rightResourcesForCount) + { + _paginationContext.TotalResourceCount = rightResourcesForCount.Count; + } + return rightValue; }