/// <summary>
        /// Base DbConnection (SqlConnection) extension for Offset Paginated Batch Query capability.
        ///
        /// Public Facade method to provide dynamically paginated results using Offset based paging/slicing.
        ///
        /// NOTE: Since RepoDb supports only Batch querying using Page Number and Page Size -- it's less flexible
        ///     than pure Offset based paging which uses Skip/Take.  Therefore, this logic provides an extension
        ///     of RepoDb core functionality; and if this is ever provided by the Core functionality
        ///     this facade will remain as a proxy to the core feature.
        ///
        /// NOTE: Cursor Slice Querying is more flexible and works perfectly for Offset Based processing also so this
        ///      represents a facade around the Cursor Page slicing that maps between Skip/Take and Cursor paging paradigm.
        ///
        /// NOTE: If the implementor needs further optimization then it's recommended to implement the optimized query
        ///      exactly as required; this should work well for many common use cases.
        ///
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="dbConnection">Extends the RepoDb BaseRepository abstraction</param>
        /// <param name="orderBy"></param>
        /// <param name="whereRawSql"></param>
        /// <param name="pagingParams"></param>
        /// <param name="tableName"></param>
        /// <param name="hints"></param>
        /// <param name="fields"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="transaction"></param>
        /// <param name="logTrace"></param>
        /// <param name="cancellationToken"></param>
        /// <returns>OffsetPageResults&lt;TEntity&gt;</returns>
        public static async Task <OffsetPageResults <TEntity> > GraphQLBatchSkipTakeQueryAsync <TEntity>(
            this DbConnection dbConnection,
            IEnumerable <OrderField> orderBy,
            RawSqlWhere whereRawSql = null, //NOTE: This Overload allows cases where NO WHERE Filter is needed...
            IRepoDbOffsetPagingParams pagingParams = default,
            string tableName                    = null,
            string hints                        = null,
            IEnumerable <Field> fields          = null,
            int?commandTimeout                  = null,
            IDbTransaction transaction          = null,
            Action <string> logTrace            = null,
            CancellationToken cancellationToken = default
            )
        //ALL entities retrieved and Mapped for Cursor Pagination must support IHaveCursor interface.
            where TEntity : class
        {
            //Slice Querying is more flexible and works perfectly for Offset Based processing also so there is no
            //  need to maintain duplicated code for the less flexible paging approach since we can provide
            //  the simplified Offset Paging facade on top of the existing Slice Queries!
            var sliceResults = await dbConnection.GraphQLBatchSliceQueryAsync <TEntity>(
                orderBy : orderBy,
                whereRawSql : whereRawSql,
                pagingParams : ConvertOffsetParamsToCursorParams(pagingParams),
                tableName : tableName,
                hints : hints,
                fields : fields,
                commandTimeout : commandTimeout,
                transaction : transaction,
                logTrace : logTrace,
                cancellationToken : cancellationToken
                ).ConfigureAwait(false);

            //Map the Slice into the OffsetPageResults for simplified processing by calling code...
            return(sliceResults.ToOffsetPageResults());;
        }
 private static IRepoDbCursorPagingParams ConvertOffsetParamsToCursorParams(IRepoDbOffsetPagingParams offsetParams)
 {
     return(new RepoDbCursorPagingParams(
                after: offsetParams?.Skip,
                first: offsetParams?.Take,
                isTotalCountRequested: offsetParams?.IsTotalCountRequested ?? false
                ));
 }
        public async Task <IOffsetPageResults <ICharacter> > GetOffsetPagedCharactersAsync(
            IEnumerable <Field> selectFields,
            IEnumerable <OrderField> sortFields,
            IRepoDbOffsetPagingParams pagingParams
            )
        {
            await using var sqlConn = CreateConnection();

            var offsetPageResults = await sqlConn.GraphQLBatchSkipTakeQueryAsync <CharacterDbModel>(
                pagingParams : pagingParams,
                orderBy : sortFields ?? DefaultCharacterSortFields,
                fields : selectFields
                );

            var convertedPage = offsetPageResults.AsMappedType(r => MapDbModelToCharacterModel(r));

            return(convertedPage);
        }
        /// <summary>
        /// Base Repository extension for Offset Paginated Batch Query capability.
        ///
        /// Public Facade method to provide dynamically paginated results using Offset based paging/slicing.
        ///
        /// NOTE: Since RepoDb supports only Batch querying using Page Number and Page Size -- it's less flexible
        ///     than pure Offset based paging which uses Skip/Take.  Therefore, this logic provides an extension
        ///     of RepoDb core functionality; and if this is ever provided by the Core functionality
        ///     this facade will remain as a proxy to the core feature.
        ///
        /// NOTE: Cursor Slice Querying is more flexible and works perfectly for Offset Based processing also so this
        ///      represents a facade around the Cursor Page slicing that maps between Skip/Take and Cursor paging paradigm.
        ///
        /// NOTE: If the implementor needs further optimization then it's recommended to implement the optimized query
        ///      exactly as required; this should work well for many common use cases.
        ///
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TDbConnection"></typeparam>
        /// <param name="baseRepo">Extends the RepoDb BaseRepository abstraction</param>
        /// <param name="orderBy"></param>
        /// <param name="whereExpression"></param>
        /// <param name="pagingParams"></param>
        /// <param name="tableName"></param>
        /// <param name="hints"></param>
        /// <param name="fields"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="transaction"></param>
        /// <param name="logTrace"></param>
        /// <param name="cancellationToken"></param>
        /// <returns>OffsetPageResults&lt;TEntity&gt;</returns>
        public static async Task <OffsetPageResults <TEntity> > GraphQLBatchSkipTakeQueryAsync <TEntity, TDbConnection>(
            this BaseRepository <TEntity, TDbConnection> baseRepo,
            IEnumerable <OrderField> orderBy,
            //NOTE: Expression is required to prevent Ambiguous Signatures
            Expression <Func <TEntity, bool> > whereExpression,
            IRepoDbOffsetPagingParams pagingParams = default,
            string tableName                    = null,
            string hints                        = null,
            IEnumerable <Field> fields          = null,
            int?commandTimeout                  = null,
            IDbTransaction transaction          = null,
            Action <string> logTrace            = null,
            CancellationToken cancellationToken = default
            )
        //ALL entities retrieved and Mapped for Cursor Pagination must support IHaveCursor interface.
            where TEntity : class
            where TDbConnection : DbConnection, new()
        {
            //Slice Querying is more flexible and works perfectly for Offset Based processing also so there is no
            //  need to maintain duplicated code for the less flexible paging approach since we can provide
            //  the simplified Offset Paging facade on top of the existing Slice Queries!
            var sliceResults = await baseRepo.GraphQLBatchSliceQueryAsync <TEntity, TDbConnection>(
                orderBy : orderBy,
                whereExpression : whereExpression,
                pagingParams : ConvertOffsetParamsToCursorParams(pagingParams),
                tableName : tableName,
                hints : hints,
                fields : fields,
                commandTimeout : commandTimeout,
                transaction : transaction,
                logTrace : logTrace,
                cancellationToken : cancellationToken
                ).ConfigureAwait(false);

            //Map the Slice into the OffsetPageResults for simplified processing by calling code...
            return(sliceResults.ToOffsetPageResults());
        }