/// <summary> /// Initializes <see cref="CollectionSegment" />. /// </summary> /// <param name="items"> /// The items that belong to this page. /// </param> /// <param name="info"> /// Additional information about this page. /// </param> /// <param name="getTotalCount"> /// A delegate to request the the total count. /// </param> public CollectionSegment( IReadOnlyCollection<T> items, CollectionSegmentInfo info, Func<CancellationToken, ValueTask<int>> getTotalCount) : base(new CollectionWrapper(items), info, getTotalCount) { Items = items; }
/// <summary> /// Initializes <see cref="CollectionSegment" />. /// </summary> /// <param name="items"> /// The items that belong to this page. /// </param> /// <param name="info"> /// Additional information about this page. /// </param> /// <param name="getTotalCount"> /// A delegate to request the the total count. /// </param> public CollectionSegment( IReadOnlyCollection <object> items, CollectionSegmentInfo info, Func <CancellationToken, ValueTask <int> > getTotalCount) { Items = items ?? throw new ArgumentNullException(nameof(items)); Info = info; _getTotalCount = getTotalCount ?? throw new ArgumentNullException(nameof(getTotalCount)); }
public void CreateCollectionSegment_ItemsNull_ArgumentNullException() { // arrange var pageInfo = new CollectionSegmentInfo(true, true); // act Action a = () => new CollectionSegment <string>( null, pageInfo, ct => throw new NotSupportedException()); // assert Assert.Throws <ArgumentNullException>(a); }
public void CreateCollectionSegment_PageInfoAndItems_PassedCorrectly() { // arrange var pageInfo = new CollectionSegmentInfo(true, true); var items = new List <string>(); // act var collection = new CollectionSegment( items, pageInfo, ct => throw new NotSupportedException()); // assert Assert.Equal(pageInfo, collection.Info); Assert.Equal(items, collection.Items); }
protected override async ValueTask <CollectionSegment> SliceAsync( IResolverContext context, object source, OffsetPagingArguments arguments) { IQueryable <TItemType> queryable = source switch { IQueryable <TItemType> q => q, IEnumerable <TItemType> e => e.AsQueryable(), _ => throw new GraphQLException("Cannot handle the specified data source.") }; IQueryable <TItemType> original = queryable; if (arguments.Skip.HasValue) { queryable = queryable.Skip(arguments.Skip.Value); } queryable = queryable.Take(arguments.Take + 1); List <TItemType> items = await ExecuteQueryableAsync(queryable, context.RequestAborted) .ConfigureAwait(false); var pageInfo = new CollectionSegmentInfo( items.Count == arguments.Take + 1, (arguments.Skip ?? 0) > 0); if (items.Count > arguments.Take) { items.RemoveAt(arguments.Take); } return(new CollectionSegment((IReadOnlyCollection <object>)items, pageInfo, CountAsync)); async ValueTask <int> CountAsync(CancellationToken cancellationToken) => await Task.Run(original.Count, cancellationToken).ConfigureAwait(false); }
protected override async ValueTask <CollectionSegment> SliceAsync( IResolverContext context, object source, OffsetPagingArguments arguments) { IQueryable <TItemType> queryable = source switch { IQueryable <TItemType> q => q, IEnumerable <TItemType> e => e.AsQueryable(), _ => throw new GraphQLException("Cannot handle the specified data source.") }; IQueryable <TItemType> original = queryable; if (arguments.Skip.HasValue) { queryable = queryable.Skip(arguments.Skip.Value); } queryable = queryable.Take(arguments.Take + 1); List <TItemType> items = await ExecuteQueryableAsync(queryable, context.RequestAborted) .ConfigureAwait(false); var pageInfo = new CollectionSegmentInfo( items.Count == arguments.Take + 1, (arguments.Skip ?? 0) > 0); if (items.Count > arguments.Take) { items.RemoveAt(arguments.Take); } Func <CancellationToken, ValueTask <int> > getTotalCount = ct => throw new InvalidOperationException(); // TotalCount is one of the heaviest operations. It is only necessary to load totalCount // when it is enabled (IncludeTotalCount) and when it is contained in the selection set. if (IncludeTotalCount && context.Field.Type is ObjectType objectType && context.FieldSelection.SelectionSet is {} selectionSet) { IReadOnlyList <IFieldSelection> selections = context .GetSelections(objectType, selectionSet, true); var includeTotalCount = false; for (var i = 0; i < selections.Count; i++) { if (selections[i].Field.Name.Value is "totalCount") { includeTotalCount = true; break; } } // When totalCount is included in the selection set we prefetch it, then capture the // count in a variable, to pass it into the clojure if (includeTotalCount) { var captureCount = original.Count(); getTotalCount = ct => new ValueTask <int>(captureCount); } } return(new CollectionSegment( (IReadOnlyCollection <object>)items, pageInfo, getTotalCount)); }