示例#1
0
        public void Range_Count_2()
        {
            // arrange
            var range = new CursorPagingRange(2, 4);

            // act
            var count = range.Count();

            // assert
            Assert.Equal(2, count);
        }
        /// <summary>
        /// Applies the pagination algorithm to the provided query.
        /// </summary>
        /// <param name="query">The query builder.</param>
        /// <param name="arguments">The paging arguments.</param>
        /// <param name="totalCount">Specify the total amount of elements</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// Returns the connection.
        /// </returns>
        public async ValueTask <Connection <TEntity> > ApplyPaginationAsync(
            TQuery query,
            CursorPagingArguments arguments,
            int?totalCount,
            CancellationToken cancellationToken)
        {
            if (query is null)
            {
                throw new ArgumentNullException(nameof(query));
            }

            var maxElementCount = int.MaxValue;
            Func <CancellationToken, ValueTask <int> > executeCount = totalCount is null ?
                                                                      ct => CountAsync(query, ct)
                : _ => new ValueTask <int>(totalCount.Value);

            // We only need the maximal element count if no `before` counter is set and no `first`
            // argument is provided.
            if (arguments.Before is null && arguments.First is null)
            {
                var count = await executeCount(cancellationToken);

                maxElementCount = count;

                // in case we already know the total count, we override the countAsync parameter
                // so that we do not have to fetch the count twice
                executeCount = _ => new ValueTask <int>(count);
            }

            CursorPagingRange range = SliceRange(arguments, maxElementCount);

            var skip = range.Start;
            var take = range.Count();

            // we fetch one element more than we requested
            if (take != maxElementCount)
            {
                take++;
            }

            TQuery slicedSource = query;

            if (skip != 0)
            {
                slicedSource = ApplySkip(query, skip);
            }

            if (take != maxElementCount)
            {
                slicedSource = ApplyTake(slicedSource, take);
            }

            IReadOnlyList <Edge <TEntity> > selectedEdges =
                await ExecuteAsync(slicedSource, skip, cancellationToken);

            var moreItemsReturnedThanRequested = selectedEdges.Count > range.Count();
            var isSequenceFromStart            = range.Start == 0;

            selectedEdges = new SkipLastCollection <Edge <TEntity> >(
                selectedEdges,
                moreItemsReturnedThanRequested);

            ConnectionPageInfo pageInfo =
                CreatePageInfo(isSequenceFromStart, moreItemsReturnedThanRequested, selectedEdges);

            return(new Connection <TEntity>(selectedEdges, pageInfo, executeCount));
        }