private async Task <IFindFluent <TEntity, TEntity> > PagingQuery <TEntity>(
            IFindFluent <TEntity, TEntity> query,
            PagedOptions <TEntity> pagedOptions,
            CancellationToken cancellationToken = default)
            where TEntity : class
        {
            if (pagedOptions.ComputeTotal)
            {
                pagedOptions.Total = await query.CountDocumentsAsync(cancellationToken);
            }

            switch (pagedOptions.Mode)
            {
            case PagedMode.Classic:
                return(query.Skip(pagedOptions.SkipCount).Limit(pagedOptions.LimitCount));

            case PagedMode.ByRange:
                var filterBuilder = Builders <TEntity> .Filter;
                var filter        = pagedOptions.GreaterThanFieldValue ?
                                    filterBuilder.Gt(pagedOptions.FieldName, pagedOptions.FieldValue) :
                                    filterBuilder.Lt(pagedOptions.FieldName, pagedOptions.FieldValue);
                filter = filterBuilder.And(filter, query.Filter);
                return(this.GetCollection <TEntity>().Find(filter).Limit(pagedOptions.LimitCount));

            case PagedMode.None:
            default:
                return(query);
            }
        }
        public async Task <List <TEntity> > ToListAsync <TEntity, TId>(
            Expression <Func <TEntity, bool> > filter,
            PagedOptions <TEntity> pagedOptions = null,
            List <OrderDefinition <TEntity> > orderDefinitions = null,
            int?skipCount     = null,
            int?limitCount    = null,
            bool asNoTracking = false,
            CancellationToken cancellationToken = default)
            where TEntity : class
        {
            var query = await BuildQuery(filter, pagedOptions, orderDefinitions, skipCount, limitCount);

            var entities = await query.ToListAsync(cancellationToken);

            if (asNoTracking)
            {
                return(entities);
            }
            else
            {
                var entitiesFromContext = entities.Select(entity => this.GetEntityFromContext <TEntity, TId>(entity, cancellationToken));

                return((await Task.WhenAll(entitiesFromContext)).ToList());
            }
        }
 private void ClearState()
 {
     this.orderDefinitions.Clear();
     this.predicate    = noFilter;
     this.pagedOptions = null;
     this.skipCount    = null;
     this.limitCount   = null;
     this.asNoTracking = false;
 }
        private async Task <IFindFluent <TEntity, TEntity> > BuildQuery <TEntity>(
            Expression <Func <TEntity, bool> > filter,
            PagedOptions <TEntity> pagedOptions,
            List <OrderDefinition <TEntity> > orderDefinitions,
            int?skipCount,
            int?limitCount)
            where TEntity : class
        {
            //TODO: colocar configureawait

            var query = this.GetCollection <TEntity>().Find(filter);

            if (pagedOptions != null && pagedOptions.Mode != PagedMode.None)
            {
                query = await this.PagingQuery(query, pagedOptions);
            }
            else
            {
                if (skipCount.HasValue)
                {
                    query = query.Skip(skipCount.Value);
                }

                if (limitCount.HasValue)
                {
                    query = query.Limit(limitCount.Value);
                }
            }

            if (orderDefinitions != null && orderDefinitions.Any())
            {
                var firstOrder   = orderDefinitions.First();
                var queryOrdered = firstOrder.IsDescending ?
                                   query.SortByDescending(firstOrder.FieldSelector) :
                                   query.SortBy(firstOrder.FieldSelector);

                foreach (var orderDefinition in orderDefinitions.Skip(1))
                {
                    queryOrdered = orderDefinition.IsDescending ?
                                   queryOrdered.ThenByDescending(orderDefinition.FieldSelector) :
                                   queryOrdered.ThenBy(orderDefinition.FieldSelector);
                }

                query = queryOrdered;
            }

            return(query);
        }
 public async Task <List <TEntity> > ToListAsync(Expression <Func <TEntity, bool> > predicate, PagedOptions <TEntity> pagedOptions)
 {
     return(await this.Where(predicate).ToListAsync(pagedOptions));
 }
        public async Task <List <TEntity> > ToListAsync(PagedOptions <TEntity> pagedOptions)
        {
            this.pagedOptions = pagedOptions;

            return(await this.ToListAsync());
        }